I placed a RenderAction inside my layout page:
#{Html.RenderAction( "LoginPartial", "Account" );}
The controller method looks like this but never seems to be called. The AccountController on the other hand does:
public ActionResult LoginPartial()
{
ApplicationUser user = this.userRepository.GetByID( User.Identity.GetUserId() );
return PartialView( "_LoginPartial", user );
}
The view looks like this:
#model Test.Domain.Entities.ApplicationUser
#using Microsoft.AspNet.Identity
#{
Layout = "";
}
...
When i run the application, I get:
HTTP Error 404.15 - Not Found
The request filtering module is configured to deny a request where the query string is too long.
And that's because the URL has come out as:
http://localhost:53744/Account/Login?ReturnUrl=%2FAccount%2FLogin%3FReturnUrl%3D%252FAccount%252FLogin%253FReturnUrl%253D%25252FAccount%25252FLogin%25253FReturnUrl%25253D%2525252FAccount%2525252FLogin%2525253FReturnUrl%2525253D%252525252FAccount%252525252FLogin%252525253FReturnUrl%252525253D%25252525252FAccount%25252525252FLogin%25252525253FReturnUrl%25252525253D%2525252525252FAccount%2525252525252FLogin%2525252525253FReturnUrl%2525252525253D%252525252525252FAccount%252525252525252FLogin%252525252525253FReturnUrl%252525252525253D%25252525252525252FAccount%25252525252525252FLogin%25252525252525253FReturnUrl%25252525252525253D%2525252525252525252FAccount%2525252525252525252FLogin%2525252525252525253FReturnUrl%2525252525252525253D%252525252525252525252FAccount%252525252525252525252FLogin%252525252525252525253FReturnUrl%252525252525252525253D%25252525252525252525252FAccount%25252525252525252525252FLogin%25252525252525252525253FReturnUrl%25252525252525252525253D%2525252525252525252525252FAccount%2525252525252525252525252FLogin%2525252525252525252525253FReturnUrl%2525252525252525252525253D%252525252525252525252525252FAccount%252525252525252525252525252FLogin%252525252525252525252525253FReturnUrl%252525252525252525252525253D%25252525252525252525252525252FAccount%25252525252525252525252525252FLogin%25252525252525252525252525253FReturnUrl%25252525252525252525252525253D%2525252525252525252525252525252FAccount%2525252525252525252525252525252FLogin%2525252525252525252525252525253FReturnUrl%2525252525252525252525252525253D%252525252525252525252525252525252FAccount%252525252525252525252525252525252FLogin%252525252525252525252525252525253FReturnUrl%252525252525252525252525252525253D%25252525252525252525252525252525252FAccount%25252525252525252525252525252525252FLogin%25252525252525252525252525252525253FReturnUrl%25252525252525252525252525252525253D%2525252525252525252525252525252525252FAccount%2525252525252525252525252525252525252FLogin%2525252525252525252525252525252525253FReturnUrl%2525252525252525252525252525252525253D%252525252525252525252525252525252525252F
Any ideas what i have done wrong?
You have to use [AllowAonymuous] on the partial view returning method in the controller
I.e.LoginPartial
Or try to add location section and set allow=* in web.config
Related
new to MVC so here goes.
I am currently loading up HTML.Partial on my Index.cshtml page like so:
#Html.Partial("~/Views/Switchb/editPerson.cshtml")
However, I am in need of customizing that in the controller depending on the current users category number.
So as an example, if the user has a category of 3 then I would need to do this:
#Html.Partial("~/Views/Switchb/3.cshtml")
Is there any type of call in the "code behind" in the controller that I can use in order to do that? Or would I just need to place the code within the cshtml page and pass its category number via the controller over to the cshtml page?
You can render a partial view from a controller action. You can pass the view name as string.
public ActionResult Switchb(string categoryNumber) {
var viewModel = new MyViewModel { CategoryNubmer = categoryNumber };
// additional processing, backend calls, formatting ....
return PartialView(categoryNumber, viewModel);
}
To call this action from View:
#{
var routeValues = new RouteValueDictionary(new {
categoryNumber= "3",
});
Html.RenderAction("Switchb", "MyController", routeValues);
}
Determine the category in the controller (via url parameter, from a database, or whatever) and then set that value as a property on your view's Model. Then in your line of code you can do this
#Html.Partial("~/Views/Switchb/" + Model.Category + ".cshtml");
Both my home controller and my "StatusController" create a new instance of a DBEntities. The Home Controller returns a _db.VMs ViewData.Model to the _Layout.cshtml view and the Status Controller returns a _db.Jobs ViewDataModel to the _GetForStatus.cshtml view as a partial view. I call the VMs ViewData model to the _Layout view like so:
#foreach (var m in ViewData.Model)
{
<li>#m.Name</li>
}
This works fine, populating the dropdown list with names of the VMs from the DB.
The _GetforStatus.
The Home Controller piece for this is written like so:
public ActionResult index()
{
_db = new IntegrationDBEntitires();
ViewData.Model = _db.VMs.ToList();
return View();
}
The StatusController is written like so:
public PartialViewResult _GetforStatus()
{
_db = new OntegrationDBEntities();
ViewData.Model = _db.Jobs.ToList();
return PartialView();
}
The _GetforStatus view is written like so:
#model IntegrationWeb.Models.Job
<div class="progress progress-striped active">
<div class="progress-bar" style="width: #((Model.IS_Progress / Model.IS_Total)*100)%"></div>
</div>
#Html.Action("_GetforStatus", "StatusController")
This is called in the _Layout view like so:\
#Html.Partial("~/Views/_GetforStatus.cshtml")
I am getting an error here. "The model item passed into the dictionary is of type 'System.Collections.Generic.List' 1[IntegrationWeb.models.VM]', but the dictionary requires model item type 'IntegrationWeb.Models.Job'.
It seems as though there is a conflict with pulling two different DBEntities into the Layout view.
How do I return a View and a Partial View to the Index Layout in ASP.NET MVC 4?
Update: I just put the Action in the Home Controller, since I can't figure out why it won't find my Controller "StatusController". Now I am getting a different error using #{Html.RenderAction("_GetforStatus");} "The Model Item passed into the dictionary is type 'System.Collections.Generic.List '1[IntegrationWeb.models.Job]', but this dictionary requires a model item of type 'IntegrationWeb.models.Job'." Anyone know what is going on here?
A partial view inherits the Model from the parent view, unless you specifically pass a property, or create another object to pass to it. They are also processed of the same request. So in your example, the controller action for the partial view isn't even being executed. What you need to do instead is use RenderAction.
#{ Html.RenderAction("_GetforStatus","ControllerName"); }
This will then allow you to to execute a view with its own model and separate request.
Instead of
#Html.Partial("~/Views/_GetforStatus.cshtml")
simply do
#Html.Action("_GetForStatus", "MyController")
Html.Partial doesn't actually hit the action, it just renders the cshtml file.
My View uses #Html.Action(…) to reflect various functional blocks. In opening the page, the site shows Authorization dialog box for users that do not have role pointed in controller method. (e.g. “manager” or “caller”) On pressing “cancel” get:
401 - Unauthorized: Access is denied due to invalid credentials.
May I achieve changes of my application behavior in case a user has no required roles, #Html.Action is ignored or nothing is shown?
My VIew:
#model InApp.ViewModel.ListViewModel
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
<div id="CallList">
#Html.Action("List","Call",new {id=Model.id})
</div>
<div class="Order">
#Html.Action("Create","Order",new {id=Model.id})
</div>
Controllers:
[Authorize(Roles = "manager, caller")] //if a user is not 'manager' or 'caller'
public PartialViewResult List() // nothing is shown
{
//...private
return PartialView();
}
[Authorize(Roles = "manager, admin")]
public PartialViewResultCreate()
{
//...private
return PartialView();
}
Trying to find the correct solution I have found similar questions:
Ignore #Html.Action() if user not in Role
and asp.net MVC3 razor: display actionlink based on user role
But I do not like “if” condition in my View. I am looking for a complex solution to hide and show separate parts using only AuthorizeAttribute and to avoid if – else in View or Controller. Thanks for any help!
I can suggest using this extension method:
This is a wrapper for #Html.Action which checks the user rights by using reflection.
public static MvcHtmlString ActionBaseRole(this HtmlHelper value, string actionName, string controllerName, object routeValues , IPrincipal user)
{
bool userHasRequeredRole = false;
Type t = Type.GetType((string.Format("MyProject.Controllers.{0}Controller",controllerName))); // MyProject.Controllers... replace on you namespace
MethodInfo method = t.GetMethod(actionName);
var attr = (method.GetCustomAttribute(typeof(AuthorizeAttribute), true) as AuthorizeAttribute);
if (attr != null)
{
string[] methodRequeredRoles = attr.Roles.Split(',');
userHasRequeredRole = methodRequeredRoles.Any(r => user.IsInRole(r.Trim())); // user roles check in depends on implementation authorization in you site
// In a simple version that might look like
}
else userHasRequeredRole = true; //method don't have Authorize Attribute
return userHasRequeredRole ? value.Action(actionName, controllerName, routeValues) : MvcHtmlString.Empty;
}
Using in view:
#Html.ActionBaseRole("List","Call",new {id=Model.id},User)
If you do not like this logic in the view - move it somewhere else. For example you can make your own extension method and use it like #Html.ActionOrNothing(...).
And the implementation should check if user has permissing to view something and return an empty string/view otherwise.
I want to redirect to a different view depending on the result of a dataset, but I keep getting returned to the page I am currently on, and can't work out why. I drop into the if statement the action gets called but once i return the view to the new page, it returns me back to the current page.
CSHTML page
#{
ViewBag.Title = "Search Results";
EnumerableRowCollection<DataRow> custs = ViewBag.Customers;
bool anyRows = custs.Any();
if(anyRows == false)
{
Html.Action("NoResults","Home");
}
// redirect to no search results view
}
Controller
public ActionResult NoResults()
{
return View("NoResults");
}
View I cant get too..
#{
ViewBag.Title = "NoResults";
}
<h2>NoResults</h2>
Change to this:
#{ Response.Redirect("~/HOME/NoResults");}
Would be safer to do this.
#{ Response.Redirect("~/Account/LogIn?returnUrl=Products");}
So the controller for that action runs as well, to populate any model the view needs.
Source
Redirect from a view to another view
Although as #Satpal mentioned, I do recommend you do the redirecting on your controller.
This clearly is a bad case of controller logic in a view. It would be better to do this in a controller and return the desired view.
[ChildActionOnly]
public ActionResult Results()
{
EnumerableRowCollection<DataRow> custs = ViewBag.Customers;
bool anyRows = custs.Any();
if(anyRows == false)
{
return View("NoResults");
}
else
{
return View("OtherView");
}
}
Modify NoResults.cshtml to a Partial.
And call this as a Partial view in the parent view
#Html.Partial("Results")
You might have to pass the Customer collection as a model to the Result action or in a ViewDataDictionary due to reasons explained here: Can't access ViewBag in a partial view in ASP.NET MVC3
The ChildActionOnly attribute will make sure you cannot go to this page by navigating and that this view must be rendered as a partial, thus by a parent view. cfr: Using ChildActionOnly in MVC
You can go to method of same controller..using this line , and if you want to pass some parameters to that action it can be done by writing inside ( new { } )..
Note:- you can add as many parameter as required.
#Html.ActionLink("MethodName", new { parameter = Model.parameter })
Okay so, i am totally new to MVC and I'm trying to wrap my head around a few of the concepts. I've created a small application...
This application has a view for creating a new Individual record. The view is bound to a model ViewPage... And I have a associated IndividualController which has a New method...
The New method of the IndividualController looks like this...
public ActionResult New()
{
var i = new Individual();
this.Title = "Create new individual...";
i.Id = Guid.NewGuid();
this.ViewData.Model = new Individual();
return View();
}
Now, the above all seems to be working. When the view loads I am able to retrieve the data from the Individual object. The issue comes into play when I try and save the data back through the controller...
In my IndividualController I also have a Save method which accepts an incoming parameter of type Individual. The method looks like...
public ActionResult Save(IndividualService.Individual Individual)
{
return RedirectToAction("New");
}
Now, on my view I wanted to use a standard html link/href to be used as the "Save" button so I defined an ActionLink like so...
<%=Html.ActionLink("Save", "Save") %>
Also, defined in my view I have created a single textbox to hold the first name as a test like so...
<% using (Html.BeginForm()) { %>
<%=Html.TextBox("FirstName", ViewData.Model.FirstName)%>
<% } %>
So, if I put a break point in the Save method and click the "Save" link in my view the break point is hit within my controller. The issue is that the input parameter of the Save method is null; even if I type a value into the first name textbox...
Obviously I am doing something completely wrong. Can someone set me straight...
Thanks in advance...
Your New controller method doesn't need to create an individual, you probably just want it to set the title and return the view, although you may need to do some authorization processing. Here's an example from one of my projects:
[AcceptVerbs( HttpVerbs.Get )]
[Authorization( Roles = "SuperUser, EditEvent, EditMasterEvent")]
public ActionResult New()
{
ViewData["Title"] = "New Event";
if (this.IsMasterEditAllowed())
{
ViewData["ShowNewMaster"] = "true";
}
return View();
}
Your Save action should take the inputs from the form and create a new model instance and persist it. My example is a little more complex than what I'd like to post here so I'll try and simplify it. Note that I'm using a FormCollection rather than using model binding, but you should be able to get that to work, too.
[AcceptVerbs( HttpVerbs.Post )]
[Authorization( Roles = "SuperUser, EditEvent, EditMasterEvent")]
public ActionResult Save( FormCollection form )
{
using (DataContext context = ...)
{
Event evt = new Event();
if (!TryUpdateModel( evt, new [] { "EventName", "CategoryID", ... }))
{
this.ModelState.AddModelError( "Could not update model..." );
return View("New"); // back to display errors...
}
context.InsertOnSubmit( evt );
context.SubmitChanges();
return RedirectToAction( "Show", "Event", new { id = evt.EventID } );
}
}
If I don't create a new Indvidual object in the New method then when my view tries to bind the textbox to the associated model I get a NullReferenceException on the below line in my view...
`<%=Html.TextBox("FirstName", ViewData.Model.FirstName)%>`
With regards to the Save method. From what I understand since my view is strongly typed shouldn't I be able to have a method signature like...
`public ActionResult New(IndividualService.Individual ind)
{
return View();
}`
I thought that was the purpose behind model binding..?
I would strongly recommend that you take a step back from what you are doing and run through some of the Tutorials/Videos here http://www.asp.net/learn/
If you have a strongly typed View it means that when the Controller picks that view to generate the output the view has better access to the Model.
However the View is not responsible for what comes back from the client subsequently such as when a form is posted or a URL is otherwise navigated to.
ASP.NET-MVC uses information in the URL to determine which Controller to hand the request off to. After that it's the controller's responsibility to resolve the various other elements in the request into instance(s) of Model classes.
The relationship between the incoming request and the controller is clouded by the significant assistance the ASP.NET-MVC routing gives the controller. For example a route can be defined to supply parameters to the controller method and thats all the controller needs and hence you don't see any code in the method relating to the http request. However it should be understood that the contoller method is simply processing a http request.
I hope you can see from the above that it would be too early in a requests life-cycle for an instance of a class from the model to passed to a public method on a controller. Its up to the controller to determine which model classes if any need instancing.