I have a _layout page which has a login box (partial view) and that view has it’s own model. So the controller looks like this:
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(LoginModel loginModel)
{
if(ModelState.IsValid)
{
var g = new GallaryImage();
var user = g.LoginUser(loginModel.Username, loginModel.Password);
if(user != null)
{
FormsAuthentication.SetAuthCookie(user.username, false);
return RedirectToAction("Index", "Home");
}
ModelState.AddModelError("", "Invalid Username/Password");
}
return View(loginModel);
}
But as soon as my main content page needs a model, my web app fails because the Login box expects a LoginModel type, but my content page is sending a different model:
This is the GET method for my main Index screen:
public ActionResult Index()
{
IndexModel model = new IndexModel();
var g = new GallaryService.GallaryImage();
var i = g.GetRandomImage();
if (i != null)
model.RandomImageUrl = "~/Images/Watermarks/" + i.filename;
return View(model);
}
So, my main content page has an IndexModel, but my partial view has a LoginModel. When I try run it, I get an error:
“The model item passed into the dictionary is of type ‘GalleryPresentation.Models.IndexModel’, but this dictionary requires a model item of type ‘GalleryPresentation.Models.LoginModel’.”
How do I handle this – My _layout needs the model for the login box.
As requested, here is the Loginbox cshtml file.
@using GalleryPresentation.Models
@model LoginModel
<script src="../../Scripts/jquery.validate.min.js" type="text/javascript"></script>
@using (Html.BeginForm("index", "Account", FormMethod.Post))
{
<table class="smallBox">
<tr>
<td>@Html.LabelFor(m => m.Username)</td>
<td>@Html.TextBoxFor(m => m.Username, new { @class = "smallText" })</td>
<td>@Html.LabelFor(m => m.Password)</td>
<td>@Html.PasswordFor(m => m.Password, new { @class = "smallText" })</td>
</tr>
<tr>
<td colspan="4" align="right"><input type="submit" value="Login"/></td>
</tr>
<tr>
<td colspan="2">@Html.ValidationSummary()</td>
</tr>
</table>
}
And the Index.cshtml file (THe main content screen) has this:
@using GalleryPresentation.Models
@model IndexModel
@{
ViewBag.Title = "Craig and Melanie's Digital Moments";
}
<br/>
<div style="text-align: center">
<img src="@Url.Content( Model.RandomImageUrl)" alt="@ViewBag.Title" />
</div>
Questions like this aren’t always the easiest to answer because there isn’t a straightforward solution. There are several issue though that should be considered. If it is possible, I would recommend that you handle login validation errors in a separate view. The partial view for the small login box then does not require a strongly-typed view model.
There’s no perfect solution, but I don’t think that it makes a lot of sense for you to always be creating
LoginModelobjects on every request that renders a view which depends on _Layout. The solution below advocates the creation of a separate login view which can be used for explicit login attempts and for the handling of any login failures.If you have any trouble following this, feel free to your question in a comment and I’ll do my best to answer.
Login Box
Account Controller
Login View