MVC4 ViewData.TemplateInfo.HtmlFieldPrefix generates an extra dot

谁都会走 提交于 2020-01-02 02:54:12

问题


I'm trying to get name of input correct so a collection of objects on my view model can get bound.

   @{ViewData.TemplateInfo.HtmlFieldPrefix = listName;}
            @Html.EditorFor(m => m, "DoubleTemplate", new { 
                Name = listName,
                Index = i,
                Switcher = (YearOfProgram >= i +1)
            })

As you can see here, I pass in the "listName" as the prefix for my template. the value of listName = "MyItems"

And here is my template:

@model Web.Models.ListElement

@if (ViewData["Switcher"] != null)
{

    var IsVisible = (bool)ViewData["Switcher"];
    var index = (int)ViewData["Index"];
    var thisName = (string)ViewData["Name"] + "[" + index + "].Value";
    var thisId = (string)ViewData["Name"] + "_" + index + "__Value";
    if (IsVisible)
    {
        @*<input type="text" value="@Model.Value" name="@thisName" id ="@thisId" class="cell@(index + 1)"/>*@
        @Html.TextBoxFor(m => m.Value, new { @class ="cell" + (index + 1)})
        @Html.ValidationMessageFor(m => m.Value)
    }
}

but I found that the generated name becomes this-> MyItems.[0].Value

It has one extra DOT

Can anyone tell me how to get rid of it?

Btw, I tried to manually specify the name inside the template and found the name gets overridden by the Html helper.

So please help about how to get rid of the extra dot.

Thanks


Update

hi @StephenMuecke the reason why I have to manually set the HtmlFieldPrefix is the property name(MyItems which is a list of objects) will get lost when MyItems is passed from main view to the partial view. By the time, the partial view called my template and passed in one object in MyItems, the template itself has no way to figure out the name of MyItems as it has been lost since the last "pass-in". So that's why I have to manually set the html field prefix name. And I even tried to use something similar to reflection(but not reelection, I forgot the name) to check the name of passed in object and found it returned "Model".

I hope my explanation make sense to you.


Update 2

I tried Stephen's approach, and cannot find the html helper PartialFor().

I even tried to use this in my main view:

Html.Partial(Model, "_MyPartialView");

In Partial View:

@model MvcApplication1.Models.MyModel
<h2>My Partial View</h2>


@Html.EditorFor(m => m.MyProperty)

Here is my templat:

@model  MvcApplication1.Models.ListElement

@Html.TextBoxFor(m => m.Value)

Here is my Model:

 public class MyModel
    {
        private List<ListElement> myProperty;
        public List<ListElement> MyProperty
        {
            get
            {
                if (myProperty == null)
                {
                    this.myProperty = new List<ListElement>() { new ListElement() { Value = 12 }, new ListElement() { Value = 13 }, new ListElement() { Value = 14 }, new ListElement() { Value = 15 }, };
                }
                return this.myProperty;
            }
            set
            {
                this.myProperty = value;
            }
        }
    }

    public class ListElement
    {
        [Range(0, 999)]
        public double Value { get; set; }
    }

And here is my controller:

public ActionResult MyAction()
{
    return View(new MyModel());
}

It only generates raw text("12131415") for me, instead of the wanted text box filled in with 12 13 14 15

But if I specified the template name, it then throws an exception saying the template view expecting ListElement, and cannot convert List into ListElement.


回答1:


There is no need set the HtmlFieldPrefix value. MVC will correctly name the elements if you use an EditorTemplate based on the property type (and without the template name).

Assumed models

public class ListElement
{
  public string Value { get; set; }
  ....
}

public class MyViewModel
{
  public IEnumerable<ListElement> MyItems { get; set; }
  ....
}

Editor template (ListElement.cshtml)

@model YourAssembly.ListElement
@Html.TextBoxFor(m => m.Value)

Main view

@model YourAssembly.MyViewModel
...
@Html.EditorFor(m => m.MyItems) // note do not specify the template name

This will render

<input type="text" name="MyItems[0].Value" ...>
<input type="text" name="MyItems[1].Value" ...>
....

If you want to do this using a partial, you just can pass the whole model to the partial

MyPartial.cshtml

@model @model YourAssembly.MyViewModel
@Html.EditorFor(m => m.MyItems)

and in the main view

@Html.Partial("MyPartial")

or create an extension method

public static MvcHtmlString PartialFor<TModel, TProperty>(this HtmlHelper<TModel> helper,
  Expression<Func<TModel, TProperty>> expression, string partialViewName)
  {
    string name = ExpressionHelper.GetExpressionText(expression);
    object model = ModelMetadata.FromLambdaExpression(expression, helper.ViewData).Model;
    var viewData = new ViewDataDictionary(helper.ViewData)
    {
      TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = name }
    };
    return helper.Partial(partialViewName, model, viewData);
  }
}

and use as

@Html.PartialFor(m => m.MyItems, "MyPartial")

and in the partial

@model IEnumerable<YourAssembly.ListElement>
@Html.EditorFor(m => m)



回答2:


  1. Call your partial this way:
@Html.Partial("_SeatTypePrices", Model.SeatTypePrices, new ViewDataDictionary
{
    TemplateInfo = new TemplateInfo() {HtmlFieldPrefix = nameof(Model.SeatTypePrices)}
})
  1. Partial view:
@model List
@Html.EditorForModel()
  1. Editor template implementation:

    @using Cinema.Web.Helpers
    @model Cinema.DataAccess.SectorTypePrice
    @Html.TextBoxFor(x => Model.Price)
    

This way your partial view will contain list of items with prefixes. And then call EditorForModel() from your EditorTemplates folder.




回答3:


I found that I can change the value of HtmlFeildPrefix in my template.

So what I did to solve my problem was just to assign the correct value to HtmlFeildPrefix in the template directly rather than in the page which calls the template.

I hope it helps.




回答4:


If I want to pass the HtmlFieldPrefix I use the following construct:

<div id="_indexmeetpunttoewijzingen">
    @Html.EditorFor(model => model.MyItems, new ViewDataDictionary()
    {
        TemplateInfo = new TemplateInfo()
        {
            HtmlFieldPrefix = "MyItems"
        }
    })
</div>                       


来源:https://stackoverflow.com/questions/25719947/mvc4-viewdata-templateinfo-htmlfieldprefix-generates-an-extra-dot

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!