What is the correct way to dynamically change the View (the view aspx) that a controller method uses versus using the standard naming convention.
I'm guessing it has something to do with the ViewResult and ViewName, but what is the correct syntax?
Update:
One thing I forgot... is there a way to do this without having the "action" or method name not be part of the resulting URL?
For example,
If I wanted to have a list of all the states in the USA.
http://localhost/list/states
(displays a simple list of state names)
And If I wanted to have a list of the 50 largest cities in the USA.
http://localhost/list/largest-cities
(displays the city and the population - two column grid)
So I'd like to be able to pull in different "formatters" depending on the list name.
Should I do that in a single action / multiple views?
Could I then use Routes to hide the View name in the URL?
What is the best way to approach this?
Just use the method that takes the name of the view to choose. Be careful, though. Most times what you probably want to do is redirect to a different action instead. Returning a different view won't change the url like redirecting will.
string name = ...figure out which view you want...
return View( name );
If you need to render a different view from a controller action dynamically, you can simply supply a value to the base.View() method (or the ViewResult constructor). The location of the view will always be (for the web forms view engine):
/Views/{Controller}/{View}.aspx
Edit: (Thanks to Ithi) It could also be in:
/Views/Shared/{View}.aspx
Related
I've spent a couple of hours trying to work out a way to do this. It's such a simple requirement that I can't believe I need to create view models or anything so grandiose.
Very simply, using MVC5, I have a View, let's call it Page1, on which there is a hyperlink. When the user clicks that hyperlink, I want them to be taken to a new View, Page2. On Page2 is an iframe. I want to set the src attribute of that iframe to the URL of Page1, the View that the user was redirected from.
So, if I could maybe use the ViewBag (which people on here don't seem to recommend), to pass the URL of Page1 from that View to the Controller for Page2, and then use Razor in my markup on Page2 to define the src attribute of the iframe, I imagine that'd work fine. Unfortunately, people don't seem to like using ViewBag, and also, I can't find an end-to-end description of how to actually achieve this in code.
Can somebody give me an appropriately straightforward solution to this problem?
A ViewModel for a View can simply be a string - so if you only need to pass a single value in to the view (the URL to use as the src), then in Page2.cshtml, you just define the model at the top like so:
#model string
To use that as the src attribute, you just do e.g.
<iframe src="#Model" .... >
And from the controller, you pass the url string as the model to the view like so:
return View("Page2", myUrlStringVariable);
So, to recap, a ViewModel doesn't necessarily have to be a new class you create - for the most basic scenarios like this, you can just use e.g. a string as the ViewModel. As soon as you start having multiple bits of data to pass in to a View, that's typically when you'd look to create a specific ViewModel class.
Another option may be a JavaScript solution. Something like...
document.getElementById('myIframe').src = document.referrer;
Given URI /admin/article/index, why would this url mapping not work?
"/admin/$controller/$action?/$id?"{
view = "/admin/index" // no dice, ignored
//action = "foo" // uncommented, this is picked up
}
I'd like for all admin controllers to use the admin view by default (and not have to render the view in each action of each controller). Same goes for "/account/$controller/..." and any other site module that should use a common view.
Perhaps there's another way to achieve this, but assumed that UrlMappings is the place to do it...
Looks like you are trying to do something very different than what you wrote.
You already have the action mapped in the base URL mapping, and the view is automatically selected based on the controller, so you need to define different mappings for those views that don't have a controller, and yet another mapping for items with a default action of foo. The default action on controllers is index, though, so there is usually no need to supply a default action without also specifying a controller.
I think you are, in general, misunderstanding how an MVC framework works. The controller should not be rendering anything, and the views should be specific to the controller/action. If multiple controllers are rendering the exact same view, I'd be willing to bet that either the controller is rendering HTML or the view is overly complicated.
You should look into Layouts with SiteMesh, which allows you to create default template structures, then just have the specific content change through views.
Reasonably new to MVC. My problem is that I have a controller that has 3 different ActionResult's which are called depending on an enum.
All three action results return the same view but with different lists as the views model. In the view the user should be able to click on an item in the list and view the details based on the ID of the item.
e.g. Site/Facilities/Libraries returns the list of libraries, Site/Facilities/Libraries/1 returns the details. This works fine when you enter the full path but on the View itself clicking the anchor
#item.Name
on an item in the list returns the Url Site/Facilities/1 instead of Site/Facilities/Libraries/1. I cant use an ActionLink as the Action to call is dynamic. I know this could be solved by creating a different View for each type but I wondered if there might be another way?
Thanks in advance.
You can use such code (a javascript trick):
#item.Name
Or, if you want to use href property, you can use such code:
<%=Html.ActionLink(item.Name, "Facilities", ViewData("ActionName"), new {id = item.ID}) %>
(In that case you have to specify ViewData("ActionName") in controller).
I would suggest that you change it so that you only have one Action, but it takes an argument instead, and depending on the argument you push different lists to the View (perhaps using 3 different "helper-functions" instead). That's at least how I would implement what you are describing!
Good luck!
I am attempting to construct an asp.net mvc app which will use the urls like:
/Controller/[Number]/Action/Id
I have got it to always call my controller and pass it the Number and the Id fine...
However I now want to return a different view depending on the Number
I could have options like:
if([Number] == 1) { return View("ViewName");}
if([Number] == 2) { return View("ViewName2");}
however I instead was wondering if there was a way to change the core so that instead of searching at ~/Views/controller/action.aspx I could have my own method which did some checking on the Number then passed to the virtual file provider is a different path
Hope this makes sense!
Decide which view to load, depending on input parameters is a controller task. You could write your own view engine.
But it is easier to return the full path to the view you want to return.
return View("~/myviews/ViewName3.aspx");
This will render ViewName3 from given directory.
You might want to look at decorating your controller method with Action Filter Attributes.
Then, you could do something special inside the Action Filter Attribute.
Or, you could pass Number to a Model object, then have the model Object return the right View path.
Either way, your instinct of trying to keep too much logic out of the Controller is sound, especially if [Number] is somehow a business concern and not a view concern.
You need to look into / google creating a custom view engine.
By the sounds of things you probably just want to extend the built-in WebFormViewEngine and just override the locations and the .FindView() method.
HTHs,
Charles
This may be more of a best practice question.
I have three views (create/details/edit) that all link to their own results view (createResults/detailsResults/editResults). Each results view shares a partial with a results table on it.
When a user submits one of the three (c/d/e) views, should each results view have its own action, even tho the action will quite literally do the exact same thing (search on the information on the c/d/e view)? I'd rather not duplicate this code if not necessary.
Should I have one action, and pass in something that tells the action which results view to direct to? Is there an easy way to get the referring view in the action?
If you have 3 actions you don't need to duplicate code. Why not refactor the common code into a single private method on the controller, or perhaps even move it into an action filter?
I would make a single action with a string parameter containing the view name.
You can play with the routing table to make the URLs prettier.