简体   繁体   中英

ASP.NET Core MVC Tag Helper for Editing Collection

I'm trying to create a custom Tag Helper that would essentially be replacing an Editor Template in versions of MVC prior to Core. I want to allow the ability to edit items in a collection. For now, I just want to be able to edit existing items but eventually would extend it to allow adding and removing items dynamically.

From what I understand this should be achievable with Tag Helpers. I can get the existing collection to display using my tag helper but the items aren't being included in the view model when the form is posted.

I have these two Tag Helpers:

SongListTagHelper.cs

[HtmlTargetElement("songlist", TagStructure = TagStructure.NormalOrSelfClosing)]
public class SongListTagHelper : TagHelper
{
    private readonly HtmlHelper _htmlHelper;

    public ICollection<SongViewModel> Songs { get; set; }

    [HtmlAttributeNotBound]
    [ViewContext]
    public ViewContext ViewContext { get; set; }

    public SongListTagHelper(IHtmlHelper htmlHelper)
    {
        _htmlHelper = htmlHelper as HtmlHelper;
    }

    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = null;

        _htmlHelper.Contextualize(ViewContext);
        var partial = await _htmlHelper.PartialAsync(
            "~/Views/Shared/TagHelperTemplates/SongList.cshtml",
            Songs);

        output.Content.SetHtmlContent(partial);
    }
}

SongTagHelper.cs

[HtmlTargetElement("song", TagStructure = TagStructure.NormalOrSelfClosing)]
public class SongTagHelper : TagHelper
{
    private readonly HtmlHelper _htmlHelper;

    public SongViewModel Song { get; set; }

    [HtmlAttributeNotBound]
    [ViewContext]
    public ViewContext ViewContext { get; set; }

    public SongTagHelper(IHtmlHelper htmlHelper)
    {
        _htmlHelper = htmlHelper as HtmlHelper;
    }

    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = null;

        _htmlHelper.Contextualize(ViewContext);
        var partial = await _htmlHelper.PartialAsync(
            "~/Views/Shared/TagHelperTemplates/Song.cshtml",
            Song);

        output.Content.SetHtmlContent(partial);
    }
}

And the respective views:

SongList.cshtml

@model ICollection<SongViewModel>

@foreach (var item in @Model)
{
    <song song="item" />
}

Song.cshtml

@model SongViewModel

<div class="row">
    <input asp-for="SongId" />
    <div class="col-md-2">
        <input asp-for="TrackNumber" placeholder="##" class="form-control" />
        <span asp-validation-for="TrackNumber" class="text-danger"></span>
    </div>
    <div class="col-md-6">
        <input asp-for="Title" placeholder="Enter Song Title" class="form-control" />
        <span asp-validation-for="Title" class="text-danger"></span>
    </div>
    <div class="col-md-4">
        <input asp-for="Duration" placeholder="00:00" class="form-control" />
        <span asp-validation-for="Duration" class="text-danger"></span>
    </div>
</div>

In my controller action I'm adding a blank item to the collection initially and passing that to the view:

var vm = new EditViewModel();
vm.SongList.Add(new SongViewModel());

return View(vm);

Then in the main view file I pass the collection to the Tag Helper like this:

<div class="form-group">
    <label class="col-md-2 control-label">Song List</label>
    <div class="col-md-10">
        <songlist songs="@Model.SongList"></songlist>
    </div>
</div>

When I run this and enter values in the TrackNumber, Title and Duration fields and submit the form, the SongList collection in the view model has 0 items.

How can I get it to properly bind to the view model when the form is submitted?

You need to use HtmlAttributeName attribute to specify what html attribute assigns the property.

...
[HtmlAttributeName("songs")]
public ICollection<SongViewModel> Songs { get; set; }
...

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