Is it possible to have a master page that has a renderpartial it in and supply a value to be passed to that partial before it is rendered.
For example we have a common menu structure across our site, I would like to put this as a partial in the master page, the problem comes in that depending on what area in the page you are we need to set a value for the selected tab so it gets highlighted and you can see where you are.
Currently the render partial is on ever page and passes in a value for the selected tab, I would like this to be in the master page and just have some way to pass the value to the master page.
I have a feeling this might be possible with the changes introduced with razor but I'm not sure, in any case we are using asp.net mvc 2 (although I'm still interested in things that would apply to more recent versions)
You could use RouteData property to get currently called page using the following:
ViewContext.ParentActionViewContext.RouteData.Values["controller"]
ViewContext.ParentActionViewContext.RouteData.Values["action"]
// OR
ViewContext.RouteData.Values["controller"]
ViewContext.RouteData.Values["action"]
Either in the controller associated with the menu or in the view itself (if it's partial). Then you can filter the output upon the current route.
Related
I am asking this question to make sure myself that I understood the subject.
"The only way to have a submit button inside a partial view is using Ajax techniques to submit the form"
Well, technically you could do a normal postback from a partial view. But that would tend to defeat the point of a partial:
the entire page would have to be re-loaded, which means the result of the partial-view postback would need to be a complete page.
the partial view's modularity suffers, because the result of its postback falls out of the partial view's scope (ie, the partial view needs to know about the entire current page).
So, it's an irregular thing to do a non-AJAX postback from a partial view. But there are scenarios where it would be useful/appropriate. Consider for example a "login" partial: you may want to post the credentials back to a specific controller/action, and have that action redirect back to the current page. In that case you could reasonably use a non-AJAX form.
The only way to have a submit button inside a partial view is using Ajax techniques to submit the form
You didn't say where you got the quote from, but this isn't true.
You submit a form from a partial view in exactly the same way you submit a form within a main view. You can do this using custom fields or by making your partial view strongly typed. Where are you getting hung up?
I'm working on a site that has routes to actions which render Partial Views. A lot of these partial views are components which together make up a complete page.
For instance on a search page I'm working on has a text box, a list of tabs, and a Table.
Seach of these can be accessed with a URL similar to
/Search/SearchPanel
/Search/Tabs/{SearchTerm}
/Search/ResultsTable/SearchTerm?tab=[currently selected tab]
and these are all rendered on with a RenderPartial on my Index page.
When the page loads, it will display each of these components the way I want it. But at the moment there's nothing stopping a user from going directly to the url
/Search/Tabs
to render only a tab control which is meaningless outside the context of the rest of the elements on the page.
Is there a way for me to prevent this?
Have you tried marking your Controller method as private?
private PartialViewResult MyPartialResultMethod()
This should allow you to call it from within your code to build up your pages and disallow any public access such as through a URl.
I'm testing this now to make doubly sure my answer is correct so I'll update as I test.
In your tabs example you could simply restrict access by using a second controller method for Tabs that's private.
So you'd have something that looks like:
public ActionResult Tabs(string searchTerm) // When a search term is passed.
and
private ActionResult Tabs() // When no search term is passed.
You could create an ActionFilter which checks if the Request.IsAjaxRequest() is true. If it's not (meaning the user is calling the view directly), re-direct accordingly.
I have a hybrid ASP.NET WebForms/MVC project. In my Master Page, I have a "menu" User Control and a "footer" User Control. Anyways. I need to pass some data (2 strings) to my "menu" User Control on my Master Page (to select the current tab in my menu navigation, etc.) My views are strongly-typed to my data model. How can I push data from my controller to my menu or at least allow my master page to access some data pre-defined in my controller?
Note: I understand this violates pure ASP.NET MVC, but like I said, it is a hybrid project. The main purpose of my introduction to ASP.NET MVC into my project was to have more control over my UI for certain situations only.
Put your strings into the ViewData collection,
ViewData["MenuString1"] = "My First String";
ViewData["MenuString2"] = "My Second String";
and retrieve them in the Master Page like this:
myMenu.Property1 = ViewData["MenuString1"].ToString();
myMenu.Property2 = ViewData["MenuString2"].ToString();
http://nerddinnerbook.s3.amazonaws.com/Part6.htm
You can use ViewData to share data between the Controller and View that is not in the model. In the Controller, do something like ViewData["menu"] = myMenu; and then in the View do <%= ViewData["menu"] %>. You can pass objects but you need to cast the ViewData[key] back to the object type in the View.
Another way to do this is to put your menus and other non-Model related data needs into a separate controller. Then you can use RenderAction to call the action in your navigation controller that generates the menu. Hack has a blog post on RenderAction that explains this in more detail.
I lean towards using ViewData for temporary values from the controller like select lists and a RenderAction for unrelated things such as the main site navigation.
We are beginning the process of moving from Web Forms to MVC for all of our new applications. I am working on porting our Master Page over and am trying to satisfy the requirements that we need a single master page to be used by all applications. The primary navigation for the application needs to be in a menu within the master page. Accomplishing this was easy, the hard part is that each application may need to determine what to display in the menu using a unique set of rules. Some apps can simply say, here's the menu structure to use via something like a SiteMap. Others need to determine what is displayed in the menu based on what roles the user has, this can also be handled easily with a SiteMap. The situation that I'm struggling with is that some apps need to generate the menus based on the roles the user has, but also on the data on which they are working. i.e. The same user may have different option in the menu for a page if they are working on object 'foo' than they do if working on object 'bar'.
What I've done at this point, is I've created an HtmlHelper that is called by the master page view and takes a list of objects of a custom type and returns an unordered list that is styled by a jQuery plugin to display the menu. The list of objects the helper method takes are passed to the view using the ViewData dictionary. Currently, the value of this ViewData node is set within the constructor of each controller. This allows each page, and potentially each method, to set a different menu without having to set the value in each action method, unless its needed. I have also created a class that parses a SiteMap and returns the list of items needed to build the menu. This class is what I'm using to set the ViewData value in the controller. The idea being that if an application needed more control of how the menu data was generated, they could create their own class to generate the data as long as it returns a list of the correct type of objects.
This solution seems to work fine so far, it just doesn't 'feel' right for some reason. I'm hoping that I can either get some ideas of better way to do this or some reassurance that this is a valid approach to solving this problem.
If it is something that will be on every page, do something like this:
Create a base controller:
public class MyBaseController : Controller
Have this controller get the data it needs and send that data in the ViewData["menu"] to the View. Then have all your controllers inherit from this one:
public class HomeController : MyBaseController
In the Master Page, loop through your ViewData and create your menu.
(I did something like this for my sub-menu which displayed a list of categories.)
In the book I am reading (Pro ASP.NET MVC Framework by Apress) they use Html.RenderAction for the menu in the masterpage. I am a Asp.net MVC novice so maybe somebody else can give more info about this.
You can download the sourcecode at apress.com though so maybe that could help.
I have an action that returns a view with a master page with a logon user control at the top. When I set outputcache, it caches the entire output including the current user, so everybody would see whoever was the last person to hit the page to refresh the cache as the current user. Is there a way to prevent the master page from being included in the cache?
I am using the following code:
[OutputCache(Duration=3000, VaryByParam={params})]
public ActionResult {actionName}({params})
{
{codeGoesHere}
}
There was a concept of "donut caching" (excluding parts of a page from the output cache) but it didn't made it in asp.net MVC 1. For solution to your problem you can try this workaround.
Output cache is associated with the controller, not the view. A controller may return different views, based on the passed parameters. Caching may also be done by parameters (like you have in your example). When the result of a controller is cached, that cached value is the view's generated html (including the master page if any). So, the short answer is, no, you can't exclude the master page from the cache.