简体   繁体   中英

asp.net mvc Html helper hidden field behaving strangely

The behavior of the HtmlHelper.Hidden eludes me.

This is from a template inside Views/Shared/DisplayTemplates/Test.cshtml. Idea was to output a delete button next to the element in the list. So the view accepts a model of IEnumerable and then uses @Html.EditorForModel() to output each test item.

So if i put this into Test.cshtml:

<input type="hidden" name="Name" value="@Model.Name"/>
@Html.Hidden("Name2", Model.Name) 

That yields this:

<input type="hidden" name="Name" value="test"/> 
<input id="RoleList_12__Name2" name="RoleList[12].Name2" type="hidden" value="test" />

Why does the name of the Html helper render something different from what i tell it to? I assume that this is intended, but i don't understand why.

Update

How would i go ahead and retrieve RoleList[12].Name in my controller?

My delete function accepts:

[HttpPost]        
public ActionResult DeleteRole(Roles.Test model)
{
}

How can that one accept a RoleList[12] name item? It always returns null if i try.

It's so that the (default) model binding will work; ie when posted the field will be resolved to RoleList[12].Name in the Controller that takes a parameter equivalent to the model class.

If your controller action doesn't reference the model class the data will silently be discarded, so that you don't have to post back entire data - but that which is posted back will be realized for you.

You can override the default model binding; see The Features and Foibles of ASP.NET MVC Model Binding


The problem with your delete is that it's at the wrong level; either you bind something to the instance of the enumerable - wrapped up in its own form (ok for small amounts of data) or you decide to have an @ActionLink into which the ID of the enumerable is passed. I generally do the second, something like:

@Html.ActionLink("Del", "DeleteRole", "Controller", new { Id = item.Id}, new { @class = "btn"})

Of course the above doesn't need a [Post] action so that'd need changing on your controller.

The above would sit in your display or edit template as appropriate.

This is happening because your view accepts IEnumerable of some model type. You basically have a list of objects passed to the view and since they all have a property named Name the binder is trying to distinguish between different instances by giving them names like model[index]property.

If you're trying to delete an instance you should have an Html.ActionLink link that invokes some action of your controller which takes the unique ID of the instance you're trying to delete. Something like this in your view:

@foreach (var item in model)
{
   @Html.ActionLink("linkText", "DeleteRole", "controllerName", new {id = item.RoleId})
}

and then your controller should have an action like this:

public ActionResult DeleteRole(int id)
{
    // Logic to delete role based on provided role ID.
    return View();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM