MVC EditorFor only rendering single property, not EditorTemplate - asp.net-mvc

Got some issues with EditorFor and I can't understand the behaviour.
I have a list of objects where I want to render an editor template based on that list.
According to https://stackoverflow.com/a/26069912 the EditorFor should render the template for each object.
public class Person
{
public string Name { get; set; }
public string PhoneNumber { get; set; }
}
The template
#model EditForTest.Models.Person
Name
<td>#Html.TextBoxFor(x => x.Name)</td>
Phone
<td>#Html.TextBoxFor(x => x.PhoneNumber)</td>
In the view I got a view model containing a list of persons. When I use
#Html.EditorFor(x => x.Persons)
the template is not rendered and somehow the first property is rendered on the page.

As #StephenMuecke mentioned I had a problem with my editor template.
Once the template was moved to the correct path /Views/Shared/EditorTemplates/Person.cshtml the editor was rendered properly.

Related

MVC Razor retrieve Description text from Model in HTML helper class

Okay I have searched it long enough to not find this anywhere on the net. So here is my question, in asp.net MVC (5.1) razor the default helper we can use DisplayNameFor to get the Name value from Display attribute is there anything similar for retrieving Description?
[Display(Name = "First Name", Description="What is your first name")]
public string FirstName { get; set; }
E.g.
#Html.DisplayNameFor(model=>model.FirstName)
Instead use LabelFor and try below code.
#Html.LabelFor(m => m.FirstName,
new{title=ModelMetadata.FromLambdaExpression<Models.Profile, string>
(m => m.FirstName, ViewData).Description})

Rendering a <textarea /> using data annotations

I'd like to render a text area for one of the fields in my model.
I've tried applying [DataType(DataType.MultilineText)] to my field, but this doesn't do the trick.
At the moment, I am rendering the text area manually but I'd much prefer to use Html.EditorFor. Any suggestions?
[DataType(DataType.MultilineText)] only works if you use Html.EditorFor helper in your view:
Sample:
Model
[DataType(DataType.MultilineText)]
public string Description { get; set; }
View
Html.EditorFor(m => m.Description)
Why not use:
#Html.TextAreaFor(model => model.YourProperty)
EditorFor helper is sort of "smart" helper and it's basing the rendering based on the underlying type of the property. If you want to enforce it to render a specific html input type then use other helpers.

Move Html.DropDownListFor into EditorTemplate

Trying to create an editor template using a dropdownlist in MVC4. I can get the dropdownlistfor to work directly in the view as such:
#Html.DropDownListFor(model => model.Item.OwnerId, new SelectList(Model.DDLOptions.CustomerOptions, "Value", "DisplayText"))
But then to "generify" it and put it into an editor template, I cannot get it to work.
Here is what I am trying in my EditorTemplate partial:
#Html.DropDownListFor(model => model, new SelectList(Model.DDLOptions.CustomerOptions, "Value", "DisplayText"))
I am getting the error:
Exception Details: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'int' does not contain a definition for 'DDLOptions'
Model.DDLOptions.CustomerOptions is of type IEnumerable<DDLOptions<int>>:
public class DDLOptions<T>
{
public T Value { get; set; }
public string DisplayText { get; set; }
}
Does this error have something to do with DDLOptions being a generic?
This line is the problem:
#Html.DropDownListFor(model => model, new SelectList(Model.DDLOptions.CustomerOptions, "Value", "DisplayText"))
Your model is simply an int, based on the code above, but then you're calling new SelectList(Model.DDLOptions.CustomerOptions, "Value", "DisplayText") in the partial too, referencing Model.DDLOptions, which does not exist in your model in the editor template. Your model is just an int.
There are several ways to do this, one of which is creating a custom model class for your item owner and have it contain the ownerID and the DDLOptions. Another would be to stick the DDLOptions in the ViewBag, but I usually stay away from that as I prefer using well-written, view-specific view models.
I hope this helps.

Can I use more than one editor template for the same class in MVC3?

I have for example a class:
public class Book
{
public int BookId { get; set; }
public string BookName { get; set; }
public string Description { get; set; }
}
and an editor template:
#model MySimpleEditorTemplate.Models.Book
#Html.DisplayFor(p => p.BookId) #Html.EditorFor(p => p.BookId)
#Html.DisplayFor(p => p.BookName) #Html.EditorFor(p => p.BookName)
#Html.DisplayFor(p => p.Description) #Html.EditorFor(p => p.Description)
I can use the editor template like this:
#Html.EditorFor(model => model.Book)
However what if I want to have two editor templates or two display templates and use one or other for the same class? Is this possible?
YES, you can have the "default" one, with its name Book.cshtml... and this one is triggered every time you use EditorFor.
You can have another editor template for Book, let's say calling it BookTheOtherWay.cshtml and there you place your "other editor view". Now, when using EditorFor, you just need to pass the template name as other parameter in the EditorFor template.
#Html.EditorFor(model => model.MyBook, "BookTheOtherWay" )
This works the same way for DisplayTemplates and the DisplayFor helper.
#Html.DisplayFor(model => model.MyBook, "BookTheOtherWay" )
Yes
public static MvcHtmlString EditorFor<TModel, TValue>(
this HtmlHelper<TModel> html,
Expression<Func<TModel, TValue>> expression,
string templateName
)
http://msdn.microsoft.com/en-us/library/ff406506.aspx
"If a template whose name matches the templateName parameter is found in the controller's EditorTemplates folder, that template is used to render the expression. If a template is not found in the controller's EditorTemplates folder, the Views\Shared\EditorTemplates folder is searched for a template that matches the name of the templateName parameter. If no template is found, the default template is used."

Partials With View Data Object

I have the following ViewData that I pass into a view.
public class MerchantSignUpViewData : BaseViewData
{
public Merchant Merchant { get; set; }
public Address Address { get; set; }
public Deal Deal { get; set; }
public List<MerchantContact> Contacts { get; set; }
public int TabIndex { get; set; }
public List<DealPricing> DealPricing { get; set; }
}
I also created 3 partial views. Merchant Info, Address, Merchant Properties
In my View I have a Deal Model that shares the same field names as Merchant which is "Name"
I can't put these in the same form cause the names will be the same.
What I ended up doing was putting all 10 partial views into one huge form (I started crying at this point) and bound like this.
<%: Html.TextBoxFor(model => model.Deal.Name)%>
<%: Html.TextBoxFor(model => model.Deal.Name)%>
This gives me the correct names of the form elements.
What I want to do is the following.
<% Html.RenderPartial("MerchantForm", Model.Merchant) %>
<% Html.RenderPartial("DealForm", Model.Deal) %>
But how do I add a prefix to all the TextBoxFor pieces or preferable the render partial tags.
Hope I provided enough information or maybe I'm just doing this the wrong way. Either will help me in the long run so thanks in advance.
Maybe I'm not quite getting the problem but I think this is exactly what Html.EditorFor(x=>x...) is for.
Create a folder called "EditorTemplates" in the same directory where your views are. Put your partials in here and give them the same name as your model type (eg rename "MerchantForm.ascx" to "Merchant.ascx").
In your main view instead of
Html.RenderPartial("MerchantForm", Model.Merchant)
use
Html.EditorFor(x=>x.Merchant)
The templating system will deal with the prefixes for you so that on post the model binder will tie everything up properly.
If you have templates set up for all the complex objects in the model you can even go a step further and on your main view just call
Html.EditorForModel()
Which will reflect over the properties in your model and call their relevant editors.

Resources