Mail z linkiem do zmiany hasła

0

Robie w moim panelu logowania zakładke "Przypomnij hasło". Problem pojawia się w linijce:

user = Membership.GetUser(foundUserName.ToString());

Za każdym razem zwraca NULL mimo że "foundUserName" zawiera prawidłową wartość. Czytałem że ".GetUser" działa tylko dla użytkowników zalogowanych..jak to można obejść? Prosze o pomoc.

Ponizej kod:

[HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult _Retrieval(RetrievalModel model)
        { 
             if (ModelState.IsValid)
   {
      MembershipUser user;
      using (var context = new EFDbContext())
      {
         var foundUserName = (from u in context.UserProfile
                              where u.eMail == model.eMail
                              select u.UserName).FirstOrDefault();
         if (foundUserName != null)
         {
            user = Membership.GetUser(foundUserName.ToString());
         }
         else
         {
            user = null;
         }
      }
      if (user != null)
      {
         // Generae password token that will be used in the email link to authenticate user
         var token = WebSecurity.GeneratePasswordResetToken(user.UserName);
         // Generate the html link sent via email
         string resetLink = "<a href='"
            + Url.Action("ResetPassword", "Account", new { rt = token }, "http") 
            + "'>Reset Password Link</a>";
 
         // Email stuff
         string subject = "Reset your password for [email protected]"";
         string body = "You link: " + resetLink;
         string from = "[email protected]";
 
         MailMessage message = new MailMessage(from, model.eMail);
         message.Subject = subject;
         message.Body = body;
         SmtpClient client = new SmtpClient();
 
         // Attempt to send the email
         try
         {
            client.Send(message);
         }
         catch (Exception e)
         {
            ModelState.AddModelError("", "Issue sending email: " + e.Message);
         }
      }         
      else 
      {
        
         ModelState.AddModelError("", "No user found by that email.");
      }
   }
            return View();
        }
1

Metoda GetUser() bez parametru zwraca informacje o aktualnie zalogowanym użytkowniku. Ta z parametrem powinna bez problemu zwrócić MembershipUser jeśli taki istnieje.

http://msdn.microsoft.com/pl-pl/library/40w5063z(v=vs.110).aspx

If you use one of the GetUser overloads that does not take a username parameter, GetUser returns the information for the current logged-on membership user. The current logged-on membership user is identified by the Name of the user in the current HttpContext.

Może ten użytkownik nie istnieje w bazie? Na pewno tam jest? :) (edit: wiem, że głupie pytanie).

A wykonanie np.

user = Membership.GetUser("mojPoprawnyLogin");

też zwraca null?

I czy nie prościej skorzystać z metody

string foundUserName = Membership.GetUserNameByEmail(model.eMail); 

?

1
AsYlum napisał(a):

Metoda GetUser() bez parametru zwraca informacje o aktualnie zalogowanym użytkowniku. Ta z parametrem powinna bez problemu zwrócić MembershipUser jeśli taki istnieje.

Może ten użytkownik nie istnieje w bazie? Na pewno tam jest? :) (edit: wiem, że głupie pytanie).

I czy nie prościej skorzystać z metody

string foundUserName = Membership.GetUserNameByEmail(model.eMail); 

?

Nie ma głupich pytań:) Tak, istnieje w bazie. Gdy podaje maila w panelu, zmienna "foundUserName" zwraca poprawnego uzytkownika który jest do niego przypisany.

No tak, siłą rzeczy gdy uzytkownik chce zmienić w tym przypadku hasło to nie może być zalogowany...

Edit: Czyli rozumiem że zamiast kombinowania z linq:

    var foundUserName = (from u in context.UserProfile
                              where u.eMail == model.eMail
                              select u.UserName).FirstOrDefault(); 

moge zastosować:

  
string foundUserName = Membership.GetUserNameByEmail(model.eMail);
0

Tak. Może trochę to kosmetyka, ale wydaje się bardziej czytelne :) Warto się upewnić czy model.eMail w ogóle zawiera poprawny adres email. Jeżeli metoda GetUserNameByEmail nie znajdzie pasującej nazwy użytkownika dla podanego adresu to zwróci null.

1

@AsYlum Przetestowałem i dalej jest problem. Wrzucam w załączniku porównanie dwóch metod. Zapytanie linq zwraca poprawną wartość natomiast powyższy sposób zwraca NULL, lecz na sam koniec i tak dostaje błąd:

The model item passed into the dictionary is of type 'iAppTest.Models.RetrievalModel', but this dictionary requires a model item of type 'iAppTest.Models.RegisterModel'.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.InvalidOperationException: The model item passed into the dictionary is of type 'iAppTest.Models.RetrievalModel', but this dictionary requires a model item of type 'iAppTest.Models.RegisterModel'.

Edit: Natomiast jesli zrobie w ten sposób to zwraca NULLA mimo że uzytkownik jest w bazie:

user = Membership.GetUser("testowy");
1
Sebastiano napisał(a):

@AsYlum Przetestowałem i dalej jest problem. Wrzucam w załączniku porównanie dwóch metod. Zapytanie linq zwraca poprawną wartość natomiast powyższy sposób zwraca NULL, lecz na sam koniec i tak dostaje błąd:

The model item passed into the dictionary is of type 'iAppTest.Models.RetrievalModel', but this dictionary requires a model item of type 'iAppTest.Models.RegisterModel'.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.InvalidOperationException: The model item passed into the dictionary is of type 'iAppTest.Models.RetrievalModel', but this dictionary requires a model item of type 'iAppTest.Models.RegisterModel'.

Wyjątek występuje przy wywołaniu GetUserNameByEmail(), a nie czasem dalej? Ta metoda spodziewa się jako parametru stringa i ten wyjątek trochę nie pasuje :)

Sebastiano napisał(a):

Edit: Natomiast jesli zrobie w ten sposób to zwraca NULLA mimo że uzytkownik jest w bazie:

user = Membership.GetUser("testowy");

Skoro Membership.GetUser("testowy") nie zwraca obiektu użytkownika dla poprawnego loginu to obstawiam problem z konfiguracją albo komunikacją membership providera z bazą.

0

Debbugowałem raz jeszcze krok po kroku całą metode. Przepływ wszystkich danych jest ok tylko problem pojawia sie na sam koniec przy:

return view(model);

Nie ma pasuje mu ten model ale nie wiem czemu, i chyba dlatego też mail nie chce się wysłac;/

1

No to prawidłowo podejrzewałem :) A co masz w widoku? Nie jest czasem tak, że masz strongly typed view i tam na górze deklarację modelu z jakiego ma korzystać? Z wyjątku wychodzi, że podajesz do widoku model typu RetrievalModel, a widok spodziewa się RegisterModel .

0

Dokładnie tak to wygląda:) tylko że w kontrolerze zwracam "RetrievalModel" i w widoku mam "RetrievalModel" bo trzeba się jakoś dostać do "m.eMail" i wyrzuca błąd że potrzebuje "RegisterModel". Jak dam "RegisterModel" to krzyczy o "LoginModel" i tak w kółko...:)
w efekcie nie wiem czym to jest spowodowane.

1

Ok. działa:) Cały problem leżał w tym że do złego modelu sie odwoływałem. Ma być w kontrolerze na końcu:

return View();

bez zwracania modelu. Całość ładnie działa i mail się wysyła na chwile obecna do katalogu lokalnego.

Mam teraz pytanie. Jak poprawnie należy skonfigurować web.config w momencie wdrożenia na serwer(aby mail wysyłał sie faktycznie na poczte)?

Obecnie jest tak:

<system.net>
    <mailSettings>
      <smtp deliveryMethod = "SpecifiedPickupDirectory" >
        <specifiedPickupDirectory  pickupDirectoryLocation = "P:\Moje\AppPanel\kod\email" />
      </smtp>
    </mailSettings>
  </system.net>
1

Powinno to wyglądać mniej więcej tak:

<system.net>
    <mailSettings>
      <smtp deliveryMethod="network" deliveryFormat="International" from="[email protected]">
		<network defaultCredentials="false" host="mailserver.example.com" enableSsl="true" port="587" userName="myUser" password="myPassword" />        
      </smtp>
    </mailSettings>
  </system.net>

Oczywiście musisz sobie dostosować ssl, port itd. do wymagań serwera.

Pomocne linki:

defaultCredentials: http://msdn.microsoft.com/en-us/library/system.net.credentialcache.defaultnetworkcredentials.aspx
deliveryFormat, deliveryMethod: http://msdn.microsoft.com/en-us/library/ms164240%28v=vs.110%29.aspx

0

O to mi właśnie chodziło. Dziękuje za pomoc;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1