I am still trying to figure out how to create reusable partial views in MVC
Lets say I would like to create a partial view to display a form for submitting an address.
Then in my ViewModel I have two addresses (Home address & Work Address)
So I would think that in my view I call HTML.Partial for each one like this
#Html.Partial("Address", Model.HomeAddress)
#Html.Partial("Address", Model.WorkAddress)
but what happens is instead of the fields having names like HomeAddress.Street, HomeAddress.City etc. they just have the regular field names Street, City, etc. so the binder on the HTTPPost action has no idea what to do with them
Thanks in advance
Partial views where not designed to handle that scenario. What you are looking for are sub-editors. Take a look at Brad Wilson's excellent series on editor templates: http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-1-introduction.html
Instead of Partial you use the EditorFor and related methods:
#Html.EditorFor(m => m.HomeAddress)
You can then use the auto-generated templates or define your own using an approach similar to partial views.
Related
I would like to use the generic razor helper function Html.Partial to render views that have common html in them.
For instance, I have two views set up in Sitecore Payment Information.cshtml and Agent Payment Information.cshtml. These are rendered using the Sitecore rendering engine. Both of these views have very similar html in them that I would like to put in razor views not set in Sitecore and call them with #Html.Partial as appose to #Html.Sitecore().Rendering() as the latter forces me to set up a view and model in Sitecore which I am not sure is necessary.
My question is, is there anything that Sitecore does behind the scenes that makes it necessary to usethe #Html.Sitecore().Rendering() helper method instead of the #Html.Partial() helper method? Everything seems to work fine and I believe the entire view should get cached since the #Html.Partial call is nested inside either the Payment Information view or the Agent Payment information view set up in Sitecore.
Thanks in advance.
I have Html.Partial working in an MVC solution using Glass for ORM. There are two ways I've used this, one where the assumed model being passed to the partial is the same as the parent rendering and another where we create the model on the fly.
Assumes parent rendering model is passed:
#Html.Partial("~/Views/Components/MyPartialView.cshtml")
Instantiates a new model that is passed in:
#Html.Partial("~/Views/Components/Navigation/SecondaryNavigationRendering.cshtml", new SecondaryNavigation())
The parent view will need to have a mapped model in Sitecore. The secondary view does not have a mapped model in Sitecore but is typed to receive the model being passed (so in my first example that would be my IBasePage model, in my second it would be my SecondaryNavigation model).
Hope this helps.
I've got a list of for example Vehicle's that I want to render in a single page, but have different view characteristics for each vehicle type.
Vehicle
- VehicleId
- VehicleTypeId (Car/Boat/Truck/etc...)
- Description
- ...
I'd like to on my main AllVehiclesPage
#foreach(var vehicle in Model) //where Model is a List<Vehicle> from AllVehicles
{
//Render proper View
//CarView(vehicle)
//BoatView(vehicle)
//TruckView(vehicle)
}
In each view it will render differently depending on the vehicle, IE Wheel rim size applies to cars/trucks not to boats etc...
I've read a number of the other questions on Stackoverflow about view inheritance, but they don't seem to apply.
Is this best to do with partial Views? Should I create Usercontrols?
Use display templates. Replace your entire foreach loop with the following line of code:
#model IEnumerable<Vehicle>
...
#Html.DisplayForModel()
And now comes the interesting part. You define display templates for each type that you want to handle:
~/Views/Shared/DisplayTemplates/Car.cshtml
~/Views/Shared/DisplayTemplates/Boat.cshtml
~/Views/Shared/DisplayTemplates/Truck.cshtml
Each template will be strongly typed to the corresponding concrete type. So here's what will happen on the Html.DisplayForModel() line:
ASP.NET MVC sees that the model is an IEnumerable<Vehicle>
ASP.NET MVC starts enumerating over this collection
For each element of the collection ASP.NET MVC looks at its concrete runtime type.
ASP.NET MVC looks for a corresponding display template for this type defined in the ~/Views/Shared/DisplayTemplates folder and automatically renders it by passing this template the current element as model.
You will notice something interesting in this pattern: I use the word ASP.NET MVC very much instead of the word the .NET developer. That's nifty because all that the developer has to do is follow the standard conventions and then ASP.NET MVC will do the job for him so that this developer doesn't need to write loops, doesn't need to write if conditions and doesn't need to reinvent wheels.
This is a quite interesting question, in my opinion.
I have a strongly typed view using the WebForm view Engine, I don't know if changing to razor would solve my problem.
PROBLEM:
I have one view with a list of cars, so of type IList <Car>.
And I have a button "Create a new Car" that popups, the popup is a form that is hidded and you call a jQuery UI command $('formName').dialog() to popup it, this form has the attributes of the possible new car, so probably a new view with a strongly typed Car. After fill in the form the database should be populated with the new car, and the list of cars should be refreshed using Ajax.
The main problem is that I can't use HTML Helpers to IList <Car> and for Car at the same time.
Briefly: What is the strongly type for that view ? Is it possible to define two views and the other one call using pop-up? Changing it to Razor would solve my problem?
Best regards,
Tito Morais
Don't mix the views for listing the cars and creating a new car together.
For instance, you can make a popup that dynamically loads a "_CreateCar" partial view, using jQuery dialog or similar component. Then when the partial view is completed, reload the list view using another Ajax call.
Maybe not so much an elegant solution is to create a complex view model like:
class ListAndCreate
{
public IList<Car> AllCars {get;set;}
public Car NewCar {get;set;}
}
IMO this is correct since that one view is responsible for listing all cars and creating a new one. Now, I'm assuming that your NewCar has values coming from your controller or something, where you need to pass a model to your view.
The other approach, that #Jonas mentions is also correct and more unitized. You could create a partial view _CreateCar with type Car, render it with Jquery/Ajax to load it into a dialog/popup and have the form POST to a Create(Car c) method in your controller.
I have an insurance entry form that has contact information for two people. I have created a Razor partial view for the contact entry and put it in the form twice. The 'master' view model (VmApplicationForm) contains two instances of a subsidiary view model (VmPolicyHolder) corresponding to the two contacts as well as some properties common to both contacts. I am calling #Html.RenderPartial("_CreateOrEdit", Model.contactInfo1) and #Html.RenderPartial("_CreateOrEdit", Model.contactInfo2) in the page. With this arrangement (no surprises) the rendered code has duplicate IDs for the form input elements.
Is there any way of getting RenderPartial to prefix the IDs and Name attributes? I couldn't see this in the documentation, but perhaps I've missed something.
Sorry, I don't have time yet to give you the example code, but i'll give you the idea. You should first create EditorTemplate for that probably called ContactInfo class. And then, in the base class(Holding that two contacts) edit view, you should write
#Html.EditorFor(model => model.contactInfo1)
#Html.EditorFor(model => model.contactInfo2)
This way, it will render that EditorTemplate and generate correct ids and names to inputs within it.
What you are doing is trying to post a collection of items in a form- this can indeed be done in MVC (as well as in any web page/application that uses a FORM tag), however it requires some special handling to avoid id collisions and to correctly format the post data. Steve Sanderson has a great post on how to accomplish this:
http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/
Essentially its a wrapper to append unique guids to element ids (in your case for each contactInfo), and create the proper array format in the tags. eg <input name="ContactInfo[f2cc4d6b-fc32-45e9-9d3d-fce54c3fede3].FirstName">
if your model is something like ContactInfo, you will end up posting like
[HttpPost]
public ActionResult Index(IEnumerable<ContactInfo> contacts)
{
// To do: do whatever you want with the data
}
So, the title should speak for itself.
To create re-usable components in ASP.NET MVC, we have 3 options (could be others i haven't mentioned):
Partial View:
#Html.Partial(Model.Foo, "SomePartial")
Custom Editor Template:
#Html.EditorFor(model => model.Foo)
Custom Display Template:
#Html.DisplayFor(model => model.Foo)
In terms of the actual View/HTML, all three implementations are identical:
#model WebApplications.Models.FooObject
<!-- Bunch of HTML -->
So, my question is - when/how do you decide which one of the three to use?
What i'm really looking for is a list of questions to ask yourself before creating one, for which the answers can be used to decide on which template to use.
Here's the 2 things i have found better with EditorFor/DisplayFor:
They respect model hierarchies when rendering HTML helpers (e.g if you have a "Bar" object on your "Foo" model, the HTML elements for "Bar" will be rendered with "Foo.Bar.ElementName", whilst a partial will have "ElementName").
More robust, e.g if you had a List<T> of something in your ViewModel, you could use #Html.DisplayFor(model => model.CollectionOfFoo), and MVC is smart enough to see it's a collection and render out the single display for each item (as opposed to a Partial, which would require an explicit for loop).
I've also heard DisplayFor renders a "read-only" template, but i don't understand that - couldn't i throw a form on there?
Can someone tell me some other reasons? Is there a list/article somewhere comparing the three?
EditorFor vs DisplayFor is simple. The semantics of the methods is to generate edit/insert and display/read only views (respectively). Use DisplayFor when displaying data (i.e. when you generate divs and spans that contain the model values). Use EditorFor when editing/inserting data (i.e. when you generate input tags inside a form).
The above methods are model-centric. This means that they will take the model metadata into account (for example you could annotate your model class with [UIHintAttribute] or [DisplayAttribute] and this would influence which template gets chosen to generate the UI for the model. They are also usually used for data models (i.e. models that represent rows in a database, etc)
On the other hand Partial is view-centric in that you are mostly concerned with choosing the correct partial view. The view doesn't necessarily need a model to function correctly. It can just have a common set of markup that gets reused throughout the site. Of course often times you want to affect the behavior of this partial in which case you might want to pass in an appropriate view model.
You did not ask about #Html.Action which also deserves a mention here. You could think of it as a more powerful version of Partial in that it executes a controller child action and then renders a view (which is usually a partial view). This is important because the child action can execute additional business logic that does not belong in a partial view. For example it could represent a shopping cart component. The reason to use it is to avoid performing the shopping cart-related work in every controller in your application.
Ultimately the choice depends on what is it that you are modelling in your application. Also remember that you can mix and match. For example you could have a partial view that calls the EditorFor helper. It really depends on what your application is and how to factor it to encourage maximum code reuse while avoiding repetition.
You certainly could customize DisplayFor to display an editable form. But the convention is for DisplayFor to be readonly and EditorFor to be for editing. Sticking with the convention will ensure that no matter what you pass into DisplayFor, it will do the same type of thing.
Just to give my 2c worth, our project is using a partial view with several jQuery tabs, and each tab rendering its fields with its own partial view. This worked fine until we added a feature whereby some of the tabs shared some common fields. Our first approach to this was to create another partial view with these common fields, but this got very clunky when using EditorFor and DropDownListFor to render fields and drop downs. In order to get the ids and names unique we had to render the fields with a prefix depending on the parent partial view that was rendering it:
<div id="div-#(idPrefix)2" class="toHide-#(idPrefix)" style="display:none">
<fieldset>
<label for="#(idPrefix).Frequency">Frequency<span style="color: #660000;"> *</span></label>
<input name="#(idPrefix).Frequency"
id="#(idPrefix)_Frequency"
style="width: 50%;"
type="text"
value="#(defaultTimePoint.Frequency)"
data-bind="value: viewState.#(viewStatePrefix).RecurringTimepoints.Frequency"
data-val="true"
data-val-required="The Frequency field is required."
data-val-number="The field Frequency must be a number."
data-val-range-min="1"
data-val-range-max="24"
data-val-range="The field Frequency must be between 1 and 24."
data-val-ignore="true"/>
#Html.ValidationMessage(idPrefix + ".Frequency")
... etc
</fieldset>
</div>
This got pretty ugly so we decided to use Editor Templates instead, which worked out much cleaner. We added a new View Model with the common fields, added a matching Editor Template, and rendered the fields using the Editor Template from different parent views. The Editor Template correctly renders the ids and names.
So in short, a compelling reason for us to use Editor Templates was the need to render some common fields in multiple tabs. Partial views aren't designed for this but Editor Templates handle the scenario perfectly.
Use _partial view approach if:
View Centric Logic
What to keep all _partial view related HTML in this view only. In the template method, you will have to keep some HTML outside the Template View like "Main Header or any outer border/settings.
Want to render partial view with logic (From controller) using URL.Action("action","controller").
Reasons to use Template:
Want to remove ForEach(Iterator). Template is well enough to identify Model as a list type. It will do it automatically.
Model Centric Logic. If multiple views are found in the same displayfor Template folder, then rendering will depend on Passed Model.
Another difference that hasn't been mentioned so far is that a partialview doesn't add model prefixes while a template does
Here is the issue