2011-05-08 38 views
4

我的任務是在一個視圖上創建登錄和註冊表單!在一個視圖上的登錄和註冊表單MVC3 Razor

我有家的感覺。在主頁上我有兩種形式,登錄和註冊。他們通過@ Html.RenderPartial(部分視圖名稱,模型)進行渲染。這種形式與帳戶控制器(登錄和註冊操作)相關。

讓我先爲您提供一些代碼...

模式

// Login model, that contains email and password 
public class Login 
{ 
    … 
} 
// Registration model that contains minimum user data, e.g. name, surname 
public class Register 
{ 
    ... 
} 
// Model for home view which contains models for both register and login 
public class Home 
{ 
    public Login LoginModel { get; set; } 
    public Register RegisterModel { get; set; } 
} 

瀏覽: Index.cshtml

@model App.Models.Home.Home 
<!-- Login Box --> 
@{ Html.RenderPartial("_LoginArea", Model.LoginModel); } 
<!-- Register Box --> 
@{ Html.RenderPartial("_RegisterArea", Model.RegisterModel); } 

_LoginArea.cshtml

@model App.Models.Account.Login 
<div style="float: left; margin-right: 100px;"> 
    <h1>@Localization.Account.Login</h1> 
    <!-- Login form --> 
    <div id="loginBox"> 
    @using (Html.BeginForm("Login", "Account", FormMethod.Post)) 
    {  
     <div class="editor-label"> 
     @Html.LabelFor(m => m.Email): 
     </div> 
     <div class="editor-field"> 
     @Html.TextBoxFor(m => m.Email) 
     @Html.ValidationMessageFor(m => m.Email) 
     </div> 
     <div class="editor-label"> 
     @Html.LabelFor(m => m.Password): 
     </div> 
     <div class="editor-field"> 
     @Html.PasswordFor(m => m.Password) 
     @Html.ValidationMessageFor(m => m.Password) 
     </div> 
     <div class="editor-label"> 
     @Html.CheckBoxFor(m => m.RememberMe) 
     @Html.LabelFor(m => m.RememberMe) 
     </div> 
     <p> 
      <input type="submit" value="@Localization.Account.Login" /> 
     </p>  
    } 
    </div> 
</div> 

_RegisterArea.cshtml

@model App.Models.Account.Register 
<div style="vertical-align: bottom;"> 
    <h1>@Localization.Account.Register</h1> 
    <div> 
    @using (Html.BeginForm("Register", "Account")) 
    { 
     //same things like in login 
    } 
    ... 

控制器:

的HomeController

// 
// GET: /Home/ 

public ActionResult Index(Home model) 
{ 
    // 
    // If logedin redirect to profile page 
    // Else show home page view 
    // 

    if (Request.IsAuthenticated) 
    { 
     return RedirectToAction("Index", "User", new { id = HttpContext.User.Identity.Name }); 
    } 
    else 
    { 
     model.LoginModel = new Login(); 
     model.RegisterModel = new Register(); 
     return View(model); 
    } 
} 

只需出示您的帳戶控制器登錄行動

// 
// POST: /Account/Login 

[HttpPost] 
public ActionResult LogIn(Login model) 
{ 
    if (Request.IsAuthenticated) 
    { 
     return RedirectToAction("Index", "User", new { id = HttpContext.User.Identity.Name }); 
    } 
    else 
    { 
     if (ModelState.IsValid) 
     { 
      if (model.ProcessLogin()) 
      { 
       return RedirectToAction("Index", "User", new { id = HttpContext.Session["id"] }); 
      } 
     } 
    } 

    //Note: this is problem part 
    // If we got this far, something failed, redisplay form 
    return View("~/Views/Home/Index.cshtml", model); 
} 

所以一切正常,但是!當模型狀態無效我有以下異常

The model item passed into the dictionary is of type 'App.Models.Account.Login', but this dictionary requires a model item of type App.Models.Home.Home'. 

我可以綁定這部分的意見和帳戶行動家居模式,但是這不是我所需要的。 我打算在其他視圖中使用_LoginArea.cshtml視圖(例如在'用戶'視圖的頁面標題中,並且該視圖有另一個模型) 因此,我需要操作方法(例如登錄)來檢索登錄模型,而不是主頁或其他任何東西。但在這種情況下,我無法將模型返回到主視圖。 我該如何解決這個問題?什麼是最合適的方式? 對不起,很多代碼,只是想清楚的事情。

回答

2

已解決!!!改用Html.RenderAction。 這裏是代碼:

Index.cshtml

<!-- Login form --> 
@{ Html.RenderAction("Login", "Account"); } 

<!-- Register form --> 
@{ Html.RenderAction("Register", "Account"); } 

部分意見是一樣的...

控制器的操作:

// 
// GET: /Account/Login 

public ActionResult Login() 
{ 
    Login model = new Login(); 

    if (TempData.ContainsKey("Login")) 
    { 
     ModelStateDictionary externalModelState = (ModelStateDictionary)TempData["Login"]; 
     foreach (KeyValuePair<string, ModelState> valuePair in externalModelState) 
     { 
      ModelState.Add(valuePair.Key, valuePair.Value); 
     } 
    } 

    return View("_LoginHome", model); 
} 

// 
// POST: /Account/Login 

[HttpPost] 
public ActionResult Login(Login model) 
{ 
    if (Request.IsAuthenticated) 
    { 
     return RedirectToAction("Index", "User", new { id = HttpContext.User.Identity.Name }); 
    } 
    else 
    { 
     if (ModelState.IsValid) 
     { 
      if (model.ProcessLogin()) 
      { 
       return RedirectToAction("Index", "User", new { id = HttpContext.Session["id"] }); 
      } 
     }     
    } 

    TempData.Remove("Login"); 
    TempData.Add("Login", ModelState); 

    // If we got this far, something failed, redisplay form 
    return RedirectToAction("Index", "Home"); 
} 

的註冊行爲同樣的事情。

正如你可以看到我使用TempData來存儲模型狀態,然後在動作開始渲染時檢索它。 其他問題是,如果模型狀態無效,我們如何才能知道應該返回的位置。我的解決方案是解析Request.UrlReferrer,就像ataddeini說的。

非常感謝我的朋友Danylchuk雅羅斯拉夫對他有幫助!

3

在這種情況下,我會建議有一箇中央登錄/註冊頁面,用戶在驗證失敗時將被重定向到。例如的目的,讓我們說這是一個名爲SiteAuthenticateLogIn(Login model)行動的情況下

因此認爲,如果驗證失敗,你會總是返回SiteAuthenticate視圖這將是強類型爲包括LoginRegister模型,非常類似於您的Home型號。

最後一個讓這種方法奏效的方法是將ReturnUrl屬性添加到LoginRegister型號。不管你希望如何填充這個,或者使用諸如Request.UrlReferrer之類的東西。通過這種方式,您將知道將用戶返回到何時最終登錄/註冊成功的時間。

所以,當一切都說過和做過,你LogIn行動可能會是這個樣子:

[HttpPost] 
public ActionResult LogIn(Login model) 
{ 
    if (Request.IsAuthenticated) 
    { 
     return RedirectToAction(model.ReturnUrl); 
    } 
    else 
    { 
     if (ModelState.IsValid) 
     { 
      if (model.ProcessLogin()) 
      { 
       return RedirectToAction(model.ReturnUrl); 
      } 
     } 
    } 

    // If we got this far, something failed. Return the generic SiteAuthenticate view 
    var saModel = new SiteAuthModel { LoginModel = model }; 
    return View("~/Views/Account/SiteAuthenticate.cshtml", saModel); 
} 

SiteAuthenticate也然後張貼回到同一Login行動。由於您已經沿着原始的RetunrUrl傳遞,如果登錄成功,則會按照計劃將使用重定向到其原始目的地。

希望有幫助,讓我知道如果有什麼不清楚或沒有意義。

相關問題