Imagine you have a View within ASP.Net MVC which have got several Partial Views embedded in it which work independently and each load their own model through Html.Action (Child Actions). Now each separate Partial View would need to load certain items from the database. In terms of performance it would be much more efficient to group all such database calls together and preload all the items of the same type with one query rather than one by one through each separate Child Action.
For example, lets say we have the following structure:
Index (View)
Main Menu (Child Action / Partial View)
This would load Sections with IDs 1 & 2
Main Content (Child Action / Partial View)
This would load Sections with IDs 3, 4, & 5
Related Sections (Child Action / Partial View)
This would load Sections with IDs 6 & 7
...
Now in the above scenario, each child action above would separately make the respective database calls to load the sections required by its own model.
In order to improve on performance, we need a way whereby before we execute each Action or Child Action, such database item requests are 'registered' and then be able to load all the items together. Then when the Action or Child Action would need to use such database items, they would have already been preloaded altogether.
We were thinking of using Action Filters which are attached to each Action & Child Action stating which items are requested but unfortunately the OnActionExecuting method is called separately prior to each action being call.
We would like something similar to Action Filters but rather than being executed prior to each call, they are executed all in the beginning of the request before any Action / Child Action is called. This way we can register all such database item requirements and load them together.
Something similar to the OnInit event within Asp.Net Web Forms whereby first the OnInit for all user controls & controls is called followed by the other events within the ASP.Net Web Forms life cycle.
Or maybe you can offer a different solution which performs similarly to what we require?
Child actions are explicitly intended for unrelated content: things you actually couldn't reasonably combine in a single DB query, anyways. If it's all related things and you can query all at once, then just add it all to a view model, and use partial views with just RenderPartial.
Actually there is no way to predict which child actions will be invoked in a view. Also you may have nested calls to child actions, invocations from the Layout, etc.
In you situation I see two ways to optimize performance:
1) Use caching - it will improve performance for the further requests, but not the first one
2) Instead of having only child actions - use partial views. In this case your main Index action will load all necessary items, build a model containing properties MenuItems, Content, RelatedSections and pass them to Index view. Then from index view you will invoke RenderPartial and pass corresponding data as a model to this partial. If you need AJAX functionality to retrieve updated part of the page - then you need to create separate actions for the each partial view.
In a short - use RenderPartial for the normal requests, and Actions for the each view in case of AJAX requests.
If you are not planning to use AJAX - then it's better to use only RenderPartial method, since Action is heavier and will work a little bit slower, since routing, instantioation of a controller, etc is involved to render HTML for child action.
Related
I am sure many people have had this question but I failed to get any results after searching the web and SO or the search keywords were different.
I am working on a new asp.net mvc web app where I get a plain template returned by the index action method on the controller. Later in the document.ready event handler I build the ui dynamically and append the dom elements to the blank template and this just works fine. My issue is I need 2 server calls here,
1) to get the view from the index action method
2) an ajax call inside the document.ready{} to get the data using which I build the ui.
I was wondering if there is any method using which I could pass back the data from the index action method along with the blank template view and use this data to create the ui inside the document.ready event handler. This will save that one additional hit to the server.
The reason for not using partial views is
1) we have some functionality already developed in jquery and
2) in my org people think making the functionality using razor and partial view will not be as flexible, for example building and raising customevent in js is a great feature that helps to keep the functionality loosely coupled from other features. (please correct if we are wrong)
Edit: I thought an example will explain this better,
Say I need to create a list of users, but the entire list and its functionality like checkboxes selection etc are built by a js module. So along with the blank view i want to pass the "users" object which is a class in my models currently.
Kindly suggest.
You have a couple of options:
1) Server-side rendering:
Putting the necessary data into the model would seem to be the obvious thing to do...that's what MVC models are for.
During the building of the HTML your View code runs - so you can access the model values in Razor code, which you can use to build your view and influence the final HTML. So in this scenario you build your view using Razor, rather than constructing it using JS code. You can of course still use JS to change it after the page has loaded, but it would be downloaded into the browser with the HTML already in the desired starting state.
2) Client-side rendering, but with necessary data pre-populated:
If you'd rather stick with your existing client-side rendering code, you could use Razor to inject some ready-made JSON into the JavaScript, so it's effectively hard-coded into the page when it first runs, rather than having to fetch it from the server separately via AJAX.
For example, if you have some object in C# which holds the data, you can serialise it to a JSON string and then use Razor to write that string into your JS in the correct place.
It's a little unclear for me on when to use a custom helper method and when to use RenderAction and also when to simply use ViewData instead. Some of their functions overlap slightly.
For example, if I were to create a Category navigation bar, would I create a new helper method and place that in some partial view? I had initially though of doing this, but I read on some blog to use RenderAction instead. I've just been thinking back and forth and could use some help not just with this example, but in general.
Assume the list of categories is coming from some data source.
The general guidelines that I follow are:
HtmlHelper methods:
Used to standardize markup. I use helpers to make sure my form fields, input buttons and image tags use consistent markup.
Used when the resulting markup is minimal. Small bits of text, form field markup, etc. I don't use helpers to render full domain objects.
Operate on a small number of discrete arguments. If I need to iterate over a collection and display something, that's a partial. If I need to take a large amount of input, that's a partial too.
Do not contain any business logic, just presentation logic. The arguments are usually objects in the solution domain, not the business/problem domain.
Are usually very general in scope and apply to large portions of the application.
Render partial:
Used when I want to decompose a large view into smaller pieces. The model should be a subset of the model of the "main" view.
Partial views are often used only by certain controllers or areas.
Render action:
Used when I want to create small chunks of functionality that can be composed in various ways.
Most often used to generate content that applies to many controllers or areas, such as navigation controls.
ViewData:
I'll use ViewData to track global data that applies to all views, such as the current user. If I need a consistent way of displaying this data I usually create a partial for it and then do RenderPartial() in a master page.
Firstly, this is probably clear, but let's say it: The category business logic (e.g. fetching data from a data source) should not be in Html-helper or in a user control: it should be done in a controller.
The difference between 1) RenderPartial / HtmlHelper vs. 2) RenderAction is in which controller this business logic is:
in the one controller action that does the whole page or
in a separate controller action specific to the partial view.
If you use your category data in pretty much every page I do not see it wrong to fetch it for each page on page-controller action level and pass it in the view data. Of course you would use some mechanism (custom model base class, extend controller, ...) so that you don't have the same category-fetching function call in each action (assuming you have lots).
If some page views choose to show the categories, some not and some perhaps have another category control with different business logic, then RenderAction is definitely better. Even in the above case, RenderAction is good: it separates the category fetching from other data in your controller actions.
Then whether to use RenderPartial or HtmlHelper... To me HtmlHelpers should be more generic and not specific to particular view or model, but this, I suppose, is more matter of taste than clear rule from MVC perspective: both should be just View-logic.
I would choose html helper methods when the scenario meets these criteria:
The arguments are not considered model data
It doesn't have to generate an excessive amount of markup
The html can be generated with just the arguments given to it
If you have an html helper method using model data or it has a lot of dependencies, its probably better as a RenderPartial or RenderAction.
I'm new also to using RenderAction
but when I need to load data for a specific piece of display I now go with
RenderAction
Ideal for loading Tag cloud, which are displayed on every page but the data is not specific to a page.
First post so please be gentle :)
When creating user controls in ASP.NET MVC, what is the best way to structure the code so that the controllers that invoke views that use the user controls do not all have to know so much about the controls? I would like to know a good way to maintain DRY while using user controls in ASP.NET MVC.
Please note, this question only pertain to user controls that require special handling and logic on a postback. I have no problem creating nice DRY code for user controls that are either view only (using RenderPartial) or that require some pre-processing to create the appropriate ViewModel (using RenderAction).
Also, this question pertains only to achieving reusable controls within an application. I am not worried about reusability between applications at this point.
To give a specific example, let's say I would like to create a 'Quick Add' user control which contains three entry fields, First Name, Last Name and Company Name and a submit button. When the QuickAdd functionality is used, the following steps should be performed independent of what page the control is on:
Validate that the fields were not empty, if they are, show an indicator.
Perform a lookup to a repository to see if the Company already exists, if not; create it.
Create a new contact associated to either the existing company or the newly created company
Re-render the existing page. If no validation errors, the user would see the exact same page again, otherwise the same page with validation errors.
My main problem with achieving DRY has to do with all the controllers that invoke views that contain the partial view end up having to have an Action Method to process the form submission from the Quick Add. Even if I break out the logic for processing the information into a separate controller and invoke that method from each of the other controllers it seems like a burden that each and every controller that invoke views that have reusable controls have to have that knowledge.
The other option I looked at was to have the reusable control always submit to a specific action method / controller but then there is no way for that controller to know how to re-populate the model appropriately for the specific controller that invoked the view that contained the reusable control (in step 4).
I am aware that there is talk of subcontrollers in MVC 2 (from this question ASP.NET MVC - Contained User Controls) but since it is not there yet, what is the best way to structure the code to achieve maximum reusability while maintaining DRY?
Is there an alternative to having to have all the controllers that invoke views that use a reusable control (with the characteristics of the one described above), having to have an Action Method to process the information from the control?
At the end of your post, you ask "Is there an alternative to having to have all the controllers... having to have an Action Method to process the information from the control"
The answer for that question is to write a custom model binder. Your custom model binder can be responsible for the populating the values from the incoming form control(s) into model or properties used by all of the controllers. Normally, you want to separate the validation from the model binding, but there is no reason that you couldn't combine them as well.
I highly recommend 6 Tips for ASP.NET MVC Model Binding for a deeper discussion of the topic along with some good references.
I'm not sure why you say the Quick Add form has to have an action method in each controller that uses it; if you wrap the Quick add functionality in a Html.BeginForm(); Html.EndForm() combo, you can have the beginform method specify the name of the action and controller, so you only need one controller.
I understand where you are coming from; it's something I have been thinking about to. While I don't know all the answers, I have some ideas for you to consider. Every controller action method is invoked via a ControllerActionInvoker class, which you can customize. This class handles invoking all of the action methods, so here you could embed certain aspects of reusable code across all or certain action methods.
Look into filters too, as there are a variety of filters that you can use or customize that fire for action methods that implement it. This way, code can run before and after the action method execution and result execution.
For validation, there is already validation components built in that will prevent page submission... you could also consider XVAL which has some other nice features. The Unity framework is an IOC container framework, which dynamic injection keeps things loosely coupled and DRY, as you can inject all kinds of references.
Also, you mentioned subcontrollers; the MVC preview has additional features you may be interested in... for instance, it has a RenderAction method that can render an action method within another action's view.
Hopefully that helps... so what am I missing?
Have a look at RenderAction and RenderPartial. Those are the canonical ways to arbitrarily inject a common control into a view.
Use RenderPartial when you want to include the data as part of your ViewData infrastructure.
Use RenderAction when you want the data to be separate from the ViewData infrastructure. The data will come from the controller method you specify in RenderAction.
Check out the NerdDinner tutorials, if you haven't done so already.
I have recently started to examine ASP.NET MVC. I have studied quite a few examples and common to these are that they contain quite simple scenarios, where a view will map to either an instance of a type in the model or a list of a paritcular type from the model.
I'm looking for guidelines to compose/composite views. In the long term I would like Ajax to be part of the equation, but for now I'm looking for a simpler non Ajax setup.
The problem
Here is a description of a contrieved problem. A domain model contains the types A and B.
class A
{ String ID, String Name, int Age
List<B> ListOfB
}
class B
{ String ID, String Name, String Url}
I would like to have a that allows the following:
A DropDownList showing type A information
Details about the particular A picked in the dropdown
A list showing type B's related to the selected type A
A form that makes it possible to edit the data of a selected type A
A form that enables the user to add a new B.
The view should not show all of this at once, instead it has to show different combinations of information and functionality according to user input. Combinations of detail and functionality could forexample be:
Initially only show the dropdownlist containing A's
If an A has been selected in the dropdown:
Show the particular A as selected in the dropdown
Show detail info about the selected A
Show list of detail info of related type B's
The user wants to edit a particular A
Show the particular A as selected in the dropdown
Show form that allows user to edit particular A
Show list of detail info of related type B's
The user wants to add a new B
Show the particular A as selected in the dropdown
Show detail info about the selected A
Show list of detail info of related type B's
That could look something like this (used the web version of balsamiq mockups - what a fantastic invention!):
Combination 2:
Combination 4:
Creating the view and controller
Since the solution has to allow for different combinations of data and functionality, I think it would be smart to have a parent view (not to be confused with a masterpage) that contained placeholders for parital views. Then, the parent views controller could make up the right combinations of model data and partial views and feed these to the parent view.
Finally; the questions:
Is my way of thinking in accordance with the asp.net mvc methodology?
Can you explain/show (not necessarily all of it) how the controller can compile the right combination of partial views and feed these to the parent view?
Can you point me towards an Ajax based solution?
Can you suggest books/links that contain examples of complex views?
asp.net mvc fully supports all of your requirements but there are few things you should get up to speed on:
You should look at implementing view models to help seperate your domain model from your specific views. Here is a good link on how to start this.
You need to get up to speed with a client side javascript framework for the ajax work with partial html rendering. jquery will do this or ms ajax. Here is an example
To your detailed questions:
Is my way of thinking in accordance with the asp.net mvc methodology?
Asp.net mvc is not going to constrain you at all so essentially this is fully supported
Can you explain/show (not necessarily all of it) how the controller can compile the right combination of partial views and feed these to the parent view?
You can use partial views if you want to seperate bits of code out and can easily refresh them by loading them independently using ms ajax or jquery. You would have a controller that mapped onto your parent view and can delegate and refresh partial views in ajax calls.
Can you point me towards an Ajax based solution?
jquery will do this or ms ajax. Here is an example
Can you suggest books/links that contain examples of complex views?
This link talks a lot about this.
I am working on an ASP.NET MVC application that contains a header and menu on each page. The menu and header are dynamic. In other words, the menu items and header information are determined at runtime.
My initial thought is to build a base Controller from which all other controllers derive. In the base controller, I will obtain the menu and header data and insert the required information into the ViewData. Finally, I will use a ViewUserControl to display the header and menu through a master page template.
So, I'm trying to determine the best practice for building such functionality. Also, if this is the recommended approach, which method should I override (I'm guessing Execute) when obtaining the data for insertion into the ViewData.
I'm sure this is a common scenario, so any advice/best-practices would be appreciated! Thanks in advance!
EDIT:
I did find the following resources after posting this (of course), but any additional anecdotes would be awesome!
http://www.singingeels.com/Blogs/Nullable/2008/08/14/How_to_Handle_Side_Content_in_ASPNET_MVC.aspx
How do you use usercontrols in asp.net mvc that display an "island" of data?
Depends on where your information is coming from. We have standard view data that we use to generate some of the information we have on screen that we create in just this fashion. It works well and is easily maintained. We override the View method to implement strongly typed view names and use this information to retrieve some of the data that the master page requires as well.
You could write a helper extension to render the header/menu
That way you could have it show in different places in the view should you need to, but only one place for maintenance.
public static HtmlString MainMenu(this HtmlHelper helper)
Use a base controller class to implement generell filter methods. The controller class implements some filter interfaces IActionFilter, IAuthorizationFilter, IExceptionFilter and IResultFilter which are usefull to implement some common behavior for all controllers.
If the menu data is the same on all pages but different for each unique user.
Generate the menudata in an OnAuthorization or Initialize method of your controller base class. First will be called on authorization. Initialize will be called before every action method. You have access to ViewData Context. Generate the menudata there.
Put the view content for menu and header into the master page and access generated ViewData there.
I tackled a similar design challenge a couple months ago - implementing a breadcrumb feature that changes as user navigates from page to page.
I overrided the OnActionExecuting method to gather the breadcrumbs and store them in ViewData (I use the name of the action as the breadCrumb of the view). Then I updated the Master page to include a user control that takes the ViewData and renders the breadcrumbs.
One thing to be aware is that if you were using the default ASP.NET MVC error handling attribute [HandleError] and your error page is using the same Master page that attempts to read the ViewData, you will soon find out that you can't access ViewData from your error page and it will raise an exception. Depending on whether you need the ViewData for failure scenarios, the viable solution is to use a separate Master page or do this: How do I pass ViewData to a HandleError View?
I'll answer your question with another question. Will the base controller have to determine what type it really is in order to generate the proper menu data? If so, then you're defeating the purpose of polymorphism and the code to generate the data should go in each controller, perhaps in OnActionExecuting if the menu is the same for all actions. Pushing it back down into a parent class seems likely to end up with some switch statement in the parent class doing what each derived controller really ought to take care of.