2012-11-09 3 views
0

내 MVC 3 아키텍처에서 중첩 된 뷰를 설정하는 데 문제가 있습니다. 현재 내가 가지고있는 것입니다 :MVC 3의 중첩 된 뷰

그래서 기본적으로 내 _Layout.cshtml 페이지는 내 마스터 페이지입니다. 그럼 Logon.cshtml이 있습니다. 이것은 내 로그온 페이지의 "마스터 페이지"역할을합니다. 그 밑에는 Login.cshtml과 ForgotPassword.cshtml이라는 부분 뷰가 있습니다. 이것 모두 뒤에 AccountController라는 컨트롤러가 있습니다. 첫째,/내가 당신이

조회수/계정 Logon.cshtml 보여 내가 로그인을 렌더링 가지고 Html.RenderAction와 부분적인 전망을 ForgotPassword Logon.cshtml

@model Coltrane.Web.Website.Models.Account.LogonViewModel 
@{ 
    Layout = "~/Views/Shared/_Layout.cshtml"; 
    ViewBag.Title = "Logon"; 
} 
@*@this.CssIncludes(@Url.Content("~/Content/login.css"))*@ 
@this.ScriptIncludes(@Url.Content("~/Content/scripts/Account/logon.js")) 
@this.InitFunctionIncludes("lga_loginTabs.init()") 
@this.InitFunctionIncludes("lga_formFocus.init()") 
<div id="container"> 
    <div class="sectionFocus noBg"> 
     <div style="margin: 24px auto; width: 450px;"> 
      <div class="customerLogo" style="margin: 24px auto;"> 
       logo 
      </div> 
      <div id="tabContainer" style="position: relative; width:100%;"> 
       <div id="login" class="box_c" style="position:absolute; width:100%;"> 
        <h1>User Login</h1> 
        <div class="box_c_content"> 
         <div class="sepH_c"> 
          @{ Html.RenderAction("Login", "Account"); } 
          <a href="#" id="gotoFogot">Forgot your password?</a> 
         </div> 
        </div> 
       </div> 
       <div id="forgot" class="box_c" style="position: absolute; width:100%;display: none;"> 
        <h1>Forgot Your Password?</h1> 
        <div class="box_c_content"> 
         <div class="sepH_c"> 
          @{ Html.RenderAction("ForgotPassword", "Account"); } 
          <a href="#" id="gotoLogin">Back to Login</a> 
         </div> 
        </div> 
       </div> 
      </div> 
     </div> 
    </div> 
</div> 

주의하자. 나는 이들 각각이 실제로 형태이고 AccountController에 게시해야하기 때문에이 작업을 수행하고 있습니다. 다음으로, 내가 당신에게 내 Login.cshtml 파일을 보여주지 :

조회수/계정/Login.cshtml

@model Coltrane.Web.Website.Models.Account.LoginViewModel 
@{ 
    Layout = null; 
} 
@this.ScriptIncludes(@Url.Content("~/Content/scripts/Account/login.js")) 
@this.InitFunctionIncludes("login.init()") 
<div class="sepH_a"> 
    <label> 
     Please enter your email and password to log into the system.</label> 
</div> 
@using (Html.BeginForm("Login", "Account", FormMethod.Post, new { id = "form_login" })) 
{ 
    <div class="sepH_a"> 
     <div class="loginError"> 
      @Html.ValidationSummary(true, "Login was unsuccessful. Please correct the errors and try again.") 
      @Html.ValidationMessageFor(m => m.UserName)<br /> 
      @Html.ValidationMessageFor(m => m.Password) 
     </div> 
    </div> 
    <div class="sepH_a"> 
     @Html.LabelFor(m => m.UserName, new { @class = "lbl_a" }) 
     <br /> 
     @Html.TextBoxFor(m => m.UserName, new { @class = "inpt_a_login", id = "lusername", name = "lusername" }) 
     <span class="inputReqd" style="visibility: visible;">*</span> 
    </div> 
    <div class="sepH_a"> 
     @Html.LabelFor(m => m.Password, new { @class = "lbl_a" }) 
     <br /> 
     @Html.PasswordFor(m => m.Password, new { @class = "inpt_a_login", id = "lpassword", name = "lpassword" }) 
     <span class="inputReqd" style="visibility: visible;">*</span> 
    </div> 
    <div class="sepH_a"> 
     @Html.CheckBoxFor(m => m.RememberMe, new { @class = "input_c", id = "remember" }) 
     @Html.LabelFor(m => m.RememberMe, new { @class = "lbl_c" }) 
    </div> 

    <div class="box_c_footer"> 
     <button class="sectB btn_a" type="submit"> 
      Login</button> 
    </div> 
} 

당신이 볼 수 있듯이을, 이것은 단순한 형태입니다. 여기에 두 가지 모델을 사용하려고합니다. 각보기마다 하나씩. 하나는 부모 용이고 다른 하나는 자식보기 용입니다 (forgotpassword에는 하나도 있습니다). 어쨌든,/내 AccountController 당신에게

컨트롤러를 표시하는 방법 [HttpPost] 로그인 (...)에

public class AccountController : Controller 
    { 
     private IAuthenticationService _authenticationService; 
     private ILoggingService _loggingService; 

     public AccountController(IAuthenticationService authenticationService, 
      ILoggingService loggingService) 
     { 
      _authenticationService = authenticationService; 
      _loggingService = loggingService; 
     } 

     public ActionResult Logon() 
     { 
      return View(); 
     } 

     [HttpGet] 
     [ChildActionOnly] 
     public ActionResult Login() 
     { 
      return PartialView(); 
     } 

     [HttpPost] 
     public ActionResult Login(LoginViewModel model, string returnUrl) 
     { 
      if (ModelState.IsValid) 
      { 
       if (Membership.ValidateUser(model.UserName, model.Password)) 
       { 
        FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe); 
        if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") 
         && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\")) 
        { 
         return Redirect(returnUrl); 
        } 
        else 
        { 
         return RedirectToAction("Index", "Home"); 
        } 
       } 
       else 
       { 
        ModelState.AddModelError("", "The user name or password provided is incorrect."); 
       } 
      } 
      else 
      { 
       ModelState.AddModelError("", "An error has occurred."); 
      } 

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

AccountController.cs

을하자, 나는 사용자 creds가 올바른지 있는지 확인하고 있습니다. 그렇다면 모든 것이 잘 작동하지만 문제는 오류입니다. 내가 return View(model)을 사용하면 return View("Logon");을 사용하는 경우 무한 루프가 발생한다고 생각합니다. Login.cshtml에 대한 부분 뷰를 얻었고 return RedirectToAction("Index", "Home");을 사용하면 올바르게 로그온 뷰로 돌아 왔지만 추가 한 오류가 발생합니다. 표시되지 않습니다 (그들은 내가 return View(model); 일 때 표시됩니다.) 여기서 잘못된 점이 무엇입니까? 내 설치가 적절하다고 생각하지만 정상적으로 작동하는 방법을 알아낼 수 없습니다. 반환을 통해 로그온을 렌더링하고 싶습니다. . 오류와 cshtml보기 그냥 완료하기 위해, 여기 내 두 ViewModels 제공된보기위한 것입니다 :

public class LogonViewModel 
{ 
} 

public class LoginViewModel 
{ 
    [Required] 
    [Display(Name = "Email")] 
    public string UserName { get; set; } 

    [Required] 
    [DataType(DataType.Password)] 
    [Display(Name = "Password")] 
    public string Password { get; set; } 

    [Display(Name = "Remember Me?")] 
    public bool RememberMe { get; set; } 
} 

답변

2
제 생각에는

이 인덱스 페이지로 다시 리디렉션하는 것입니다 처리 할 수있는 가장 좋은 방법 그러나한다. 언급하면 오류가 발생합니다.

그래도 좋은 해결책이 있습니다 - 모델 상태를 TempData에 저장하고 인덱스 페이지에 다시 가져옵니다. [ImportModelStateFromTempData][ExportModelStateToTempData]

http://weblogs.asp.net/rashid/archive/2009/04/01/asp-net-mvc-best-practices-part-1.aspx#prg

+0

최고를! 나는 더 가깝다! ImportModelStateFromTempData에서 Logon.cshtml을 렌더링 할 때 오류가 발생하는 것을 볼 수 있지만 오류가 발생하지만 Login.cshtml (하위 부분 뷰)을 렌더링하면 다른 부분을 치고 제거하는 중입니다. 따라서 오류가 발생해야하는보기가 계속 손실됩니다. 부모보기는 기본적으로 그들을 먹고 있습니다. 생각? –

+0

@Tyler -'ViewResult'와'PartialViewResult'가 모두'ViewResultBase'를 확장하기 때문에 결과가'ViewResult' 대신에'ViewResultBase' 타입인지 확인하기 위해'if' 문을 변경하는 것이 쉬운 문제입니다. 그러나 다른 부분 뷰에도 오류를 표시 할 영역이 있으면 두 번 표시 될 수 있습니다. 또 다른 방법은 Login.cshtml 대신 Logon.cshtml에 두 부분의 오류를 표시하는 것입니다. –

+0

도움 주셔서 감사합니다. ViewResultBase 사용에 대한 귀하의 제안을 사용하여 종료되었습니다. 내보내기에서 오류를 던진 작업 이름과 함께 tempdata 값을 추가하여 중복 된 오류 표시를 방지했습니다. 가져 오기 필터는 현재 작업이 tempdata의 작업과 일치하는 경우에만 모델 상태를 병합합니다. 또한 가져 오기/내보내기 및 ViewResult를 사용하여 상위 뷰로 오류를 버블 링하는 또 다른 필터를 만들 수도 있습니다. 다시 한 번 감사드립니다! –

0

내가 문제가 사용하고있는 방법이라고 생각 : 여기이 꽤 원활하게하는 데 사용할 수있는 몇 가지 좋은 특성을 제공하는 링크입니다.

@Html.RenderAction("Login", "Account") 

은 연결된 데이터가없는 GET 로그인을 항상 호출합니다. 사용

시도 : 모델 LogonViewModel 및 LoginModel입니다

@Html.RenderPartial("Login","Account", Model.LoginModel) 

는 LoginViewModel이다.

귀하의 LogonViewModel이 될 것입니다 :

public class LogonViewModel 
{ 
    public LoginViewModel LoginModel { get; set; } 
} 

그런 다음 AccountController에 당신이 뭔가를 같이 할 수있는 :

var logonModel = new LogonViewModel(); 
    logonModel.LoginModel = model; 

    return View("Logon", logonModel);