The Scenario is this...I goto the login screen on my web app. I login with wrong username/password. I get an error on the line in my HTML for tab-6 #HTML.Partial("../../Account/Register") because the RegisterModel is not passed in(Exact error below). Well I'm not doing anything with the Register screen, just logging in.
However, I think the problem is because the Register section is always loaded. So I'm thinking, I don't need to pass in both LogOnModel and RegisterModel, to fix the problem, but maybe should not load the Register page until it is specifically called, I think? Is that the correct thing to do and how would I load the Register page only when it is called/clicked. I'm using JQuery UI tabs and asp.net mvc.
ERROR:
The model item passed into the dictionary is of type 'Portal.Web.Models.LogOnModel', but this dictionary requires a model item of type 'Portal.Web.Models.RegisterModel'.
Thanks a lot!
<div id="tabs" class="ui-tabs ui-widget ui-widget-content ui-corner-all" style=" position:relative; border:0px;" >
<ul class="ui-tabs-nav">
<li><a href="#tabs-1" >Home</a></li>
<li><a href="#tabs-2" >Statistics</a></li>
<li><a href="#tabs-3" >Topo Maps</a></li>
<li><a href="#tabs-4" >FAQs</a></li>
<li style="display:none;">Login</li>
<li style="display:none;">SignUp</li>
</ul>
<div id="tabs-1" class="ui-tabs-hide ui-tabs-panel">#Html.Partial("../Home/Home") </div>
<div id="tabs-2" class="ui-tabs-hide ui-tabs-panel">#Html.Partial("../Statistics/Statistics")</div>
<div id="tabs-3" class="ui-tabs-hide ui-tabs-panel">#Html.Partial("../Maps/Maps")</div>
<div id="tabs-4" class="ui-tabs-hide ui-tabs-panel">#Html.Partial("../Home/FAQs")</div>
<div id="tabs-5" class="ui-tabs-hide ui-tabs-panel">#Html.Partial("../Account/LogOn")</div>
<div id="tabs-6" class="ui-tabs-hide ui-tabs-panel">#Html.Partial("../Account/Register")</div>
</div>
Here is my AccountController with action method
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
FormsService.SignIn(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
return View(model);
}
As Requested Here is the additional code:
public ActionResult LogOn()
{
return View();
}
Double-check that you've set your partial view to inherit from the appropriate model. At the top of your partial view code, you should have a line like this.
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Portal.Web.Models.LogOnModel>" %>
Related
I'm using MVC4 with C# and I have a shared _Layout view that has a link to the home page, "index" via the "homeController".
<p class="site-title">
#if (controller = Roles) {
<a href="~/Roles/Index/" id="logo-holder">
} else {
<a href="~/Home/Index/" id="logo-holder">}
<img class="navbar-header" alt="logo"
src="~/Images/Comtrex_Logo_Blue_&_Orange.png" height="60"
width="302">
<span style="padding-top:2em">Cloud Reporting</span>
</a>
</p>
How can I add and if else statement to navigate to different links depending on the view that the user is currently on?
I'm an intern working on some quality-of-life improvements for a site. Nothing essential, but since this is actually going to be deployed I want to keep things tidy.
I need to pull a table from a database, and display it in in a shared header on a site. I already have the database set up, the model getting data from the database, and a test view just to see if it's displaying correctly. However, the model is being passed by the page controller through the viewbag, which I've been told not to do.
So, how can I have my page print out my model data without passing it through a viewbag?
You can do that using this format
public ActionResult Index(YourModelHere model)
{
return View(model);
}
In your view, add this
#model yournamespacehere.Models.YourModelHere
UPDATE
Create a new controller for partial view data
//partial view call
public ActionResult GetHeaderPartial()
{
var model = new DataModel();
model.data1 = "Menu 1";
model.data2 = "Menu 2";
return PartialView("_HeaderPartial", model);
}
Create the Partial View for the shared header. In this example, i've named it as "_HeaderPartial"
#model yournamespace.Models.DataModel
<li>#Model.data1</li>
<li>#Model.data2</li>
In your shared header layout, add #Html.Action("GetHeaderPartial","ControllerHere")
<header>
<div class="content-wrapper">
<div class="float-left">
<p class="site-title">#Html.ActionLink("your logo here", "Index", "Home")</p>
</div>
<div class="float-right">
<section id="login">
#Html.Partial("_LoginPartial")
</section>
<nav>
<ul id="menu">
<li>#Html.ActionLink("Home", "Index", "Home")</li>
<li>#Html.ActionLink("About", "About", "Home")</li>
<li>#Html.ActionLink("Contact", "Contact", "Home")</li>
#Html.Action("GetHeaderPartial","Sample")
</nav>
</div>
</div>
</header>
Here's a good place to start. As the article states, there are basically three ways to pass data to the view:
ViewBag
Dynamic objects
Strongly Typed objects
With the latter approach (generally a good idea), you just have to pass the model instance to the ActionResult you're returning (in your case, that would be a ViewResult instance).
So instead of this....
public ActionResult Index()
{
ViewBag.Foo= new Foo();
return View();
}
you do this...
public ActionResult Index()
{
return View(new Foo());
}
Make sure your model in the Index view has the following line:
#model Foo
Now you can use Razor or whatever syntax you're using to do what you need to do in your view.
Setup a view model that is created in the controller and passed to the view. This link will help you!
I am working on an MVC5 application with C# back-end. I am attempting to get change /Controller/Action?parameter=value show as /Controller/Action/Value.
Currently I have an action link on a page setup in hopes to be able to view the user's profile info:
#{ var test = new RouteValueDictionary {{"username", "testman"}}; }
<h2>#ViewBag.Title</h2>
<div class="row">
<div class="col-md-2" style="border-right:1px solid #EEE; min-height: 250px;">
Sidebar 1
</div>
<div class="col-md-8">
test link
</div>
<div class="col-md-2" style="border-left:1px solid #EEE; min-height: 250px;">
Sidebar 2
</div>
</div>
And here is the Action:
[RequireRequestValue(new[] { "username" })]
[Route("Test/{username}")]
public ActionResult Test(string username)
{
var route = RouteData.Route;
try
{
ViewBag.Page = 9;
ViewBag.Title = "Testing";
ViewBag.Message = username;
return View();
}
catch (Exception ex)
{
var error = new HandleErrorInfo(ex, "Home", "Test");
ViewBag.errorMessage = ex.Message;
return View("Error", error);
}
}
I have added routes.MapMvcAttributeRoutes(); to my RouteConfig.cs file.
If I do not add the [Route("Test/{username}")] Attribute to my action, the link renders like this: Home/Test?username=testman. If I add the Attribute the link renders to my liking: Home/Test/testman.
Unfortunately, I get this server 500 error when I click on the link, and this is where I have been stuck:
No matching action was found on controller '<project>.Controllers.HomeController'.
This can happen when a controller uses RouteAttribute for routing, but no action on
that controller matches the request.
For fun I even tried creating an explicit ActionResult to see if I could get something different, but no luck there.
I am obviously missing something...can anyone help me get on the right track?
Thanks!
I'm trying to build an inbox that is very similar to facebooks message inbox, where you have a list of conversations(I only want a list of a message title) and when you click the conversation or message title in my situation, I want the whole message to be rendered next to it in a partial view.
Here's my Inbox view:
#model BlocketProject.Models.ViewModels.ProfilePageViewModel
#{
ViewBag.Title = "Inbox";
}
<h2>Dina meddelanden:</h2><br />
<div class="left">
<table id="messageTable">
#foreach (var message in Model.UserMessages)
{
<tr>
<td>
<button type="submit" class="messageButton">
#if (message.Unread == true)
{
<h4 style="font-weight:bold;">#message.MessageTitle</h4>
}
else if (message.Unread == false)
{
<h4>#message.MessageTitle</h4>
}
</button>
</td>
</tr>
}
</table>
</div>
<div class="right">
#Html.Partial("ReadMessage")
</div>
When I click this message-element that is a button, I want to pass that messageId to the PartialView ReadMessage:
#model BlocketProject.Models.DbClasses.DbMessages
<h2>#Model.MessageTitle</h2><br />
<p>#Model.MessageText</p>
and the controller looks like this:
[HttpPost]
public ActionResult Inbox()
{
var allMessages = ConnectionHelper.GetAllMessages(ConnectionHelper.GetUserByEmail(User.Identity.Name).UserId);
var model = new ProfilePageViewModel();
model.UserMessages = allMessages;
return View("Inbox", model);
}
[HttpPost]
public ActionResult ReadMessage(int messageId)
{
var model = ConnectionHelper.GetMessageByMessageId(messageId);
return PartialView("ReadMessage", model);
}
I've tried passing the messageId through a post as you can see in my controller, but then the partialView is returned as a new page and I simply want to render it in the Inbox view.
Any ideas?
EDIT:
Jonesy's answer fixed my problem when I edited it like this:
Controller:
public ActionResult ReadMessage(int messageId)
{
var model = ConnectionHelper.GetMessageByMessageId(messageId);
return PartialView("ReadMessage", model);
}
View:
<div class="left">
<table id="messageTable">
#foreach (var message in Model.UserMessages)
{
<tr>
<td>
#using (Ajax.BeginForm("ReadMessage", new { #messageId = message.MessageId }, new AjaxOptions { UpdateTargetId = "showMessage" }, FormMethod.Post))
{
<button type="submit" class="messageButton">
#if (message.Unread == true)
{
<h4 style="font-weight:bold;">#message.MessageTitle</h4>
}
else if (message.Unread == false)
{
<h4>#message.MessageTitle</h4>
}
</button>
}
</td>
</tr>
}
</table>
</div>
<div class="right" id="showMessage">
#Html.Partial("ReadMessage", new BlocketProject.Models.DbClasses.DbMessages())
</div>
Razor is run on the server, before the page is rendered. Once the page is on the client, and they can click a message, the concept of the PartialView is gone - it's all just one HTML page.
The easiest way for you to do this is to use an Ajax.BeginForm where your button is, and on click, update an element with a partial view retrieved from the server. Something like:
#using(Ajax.BeginForm("ReadMessage", "Messages", new AjaxOptions() { UpdateTargetId = "showMessage" })) {
//...
}
//...
<div class="right" id="showMessage">
//ReadMessage partial rendered on button click
</div>
A little method that could help you :
protected ActionResult View(string viewName, object model)
{
if (ControllerContext.IsChildAction)
return PartialView(viewName, model);
else if (Request.IsAjaxRequest())
return PartialView(viewName, model);
else
return View(viewName, model);
}
This will return a PartialView when you call you action via #Html.RenderAction() or call the action via Ajax (jQuery).
You can then use jQuery to prevent the form to be posted and post it with Ajax or when you click on a message, you can also use jQuery to get the result from the action and insert it in your DOM.
I'm just wrapping up a college project, I'm not sure if I've been staring at my computer for too long and am missing something obvious, but when I try to log a user out, I'm getting a 404 not found for the URL /Account/LogOff.
I have a navbar that shows Log in/Log out depending on whether a user is, logged in, or, logged out:
<div class="nav-collapse collapse">
<ul class="nav pull-right">
<li class="dropdown" id="dropdown-login-div">
#if (!Request.IsAuthenticated)
{
<a class="dropdown-toggle" href="#" data-toggle="dropdown">Sign In <strong class="caret"></strong></a>
}
else
{
#Html.ActionLink("Log Off", "LogOff", "Account")
}
<div class="dropdown-menu" id="dropdown-login">
#Html.Partial("~/Views/Account/_LoginPartial.cshtml", new ViewDataDictionary<LetLord.Models.LoginModel>())
</div>
</li>
</ul>
</div>
In my Account controller the default LogOff action that comes with the Internet template:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
WebSecurity.Logout();
return View("Index");
}
Could someone tell me why this happening - before I throw my laptop against the wall. Cheers.
You use a link (<a/> tag) to log off which results in HTTP GET request when user clicks on it, but your action is constrained to serve POST request only (because it is decorated with [HttpPost] attribute).
You either need to put your link into a form and generate POST request, or remove [HttpPost] and [ValidateAntiForgeryToken] (credits to GalacticCowboy) from your action.
Since logout modifies server state, I wouldnt remove [HttpPost] and [ValidateAntiForgeryToken]
Instead I will replace the link (anchor tag) with the following
#using (Html.BeginForm("Log Out", "Account", FormMethod.Post,
new { id = "logoutForm" }))
{
#Html.AntiForgeryToken()
Log Out
}
I ran into this issue on a legacy app. The way that I fixed it was to detect when the supplied return Url was '/Account/LogOff' and act accordingly.
From the 'AccountController.cs' file, 'Login' method:
if (returnUrl == "/Account/LogOff")
{
return this.RedirectToLocal(null);
}
else
{
return this.RedirectToLocal(returnUrl);
}