为什么我的视图模型属性没有发送回服务器?

huangapple go评论98阅读模式
英文:

Why isn't my view model's property being sent back to the server?

问题

ASP.NET Core 7 MVC - 视图模型的属性未被发送回服务器。

我有两个实体它们之间有多对多的关系:

public class Trip
{
    [Key]
    public Guid TripId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    [ValidateNever]
    public IEnumerable<Tag> Tags { get; set; }
}

public class Tag
{
    [Key]
    public Guid TagId { get; set; }
    public string Name { get; set; }

    [ValidateNever]
    public IEnumerable<Trip> Trips { get; set; }
}

当我创建一个新的 Trip 时,我想要能够使用复选框选择多个标签。为此,我创建了两个视图模型:

public class SelectTagViewModel
{
    public string TagId { get; set; }
    public string TagName { get; set; }
    public bool IsSelected { get; set; } = false;
}

public class CreateTripViewModel
{
    public Trip Trip { get; set; }
    [ValidateNever]
    public List<SelectTagViewModel> Tags { get; set; }
}

这是控制器:

public class TripController : Controller
{
    private readonly ITripRepository _tripRepository;
    private readonly ITagRepository _tagRepository;

    public TripController(ITripRepository tripRepository, ITagRepository tagRepository)
    {
        _tripRepository = tripRepository;
        _tagRepository = tagRepository;
    }

    public async Task<IActionResult> Index()
    {
        var trips = await _tripRepository.GetAllTripsAsync(null, "Tags");
        return View(trips);
    }

    public async Task<IActionResult> Create()
    {
        List<SelectTagViewModel> tagsList = (await _tagRepository.GetAllTagsAsync(null)).Select(
            u => new SelectTagViewModel
            {
                TagId = u.TagId.ToString(),
                TagName = u.Name
            }).ToList();

        CreateTripViewModel viewModel = new()
        {
            Trip = new(),
            Tags = tagsList
        };

        return View(viewModel);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create(CreateTripViewModel createTripViewModel)
    {
        if (ModelState.IsValid)
        {
            await _tripRepository.AddTripAsync(createTripViewModel.Trip);

            return RedirectToAction(nameof(Index));
        }
        return View(createTripViewModel);
    }
}

这是 Create 操作的视图:

@using TestApplication.ViewModels;
@model CreateTripViewModel

<div class="card shadow border-0 mt-4" style="margin-left:20vw; margin-right:20vw;">
    <div class="card-header bg-primary m-lg-0 py-3">
        <div class="row">
            <div class="col-12 text-center">
                <h2 class="text-white py-2">Create Trip</h2>
            </div>
        </div>
    </div>
    <div class="card-body p-4">
        <form method="post" class="row px-5" asp-action="Create">
            <div class=" d-flex justify-content-center">
                <div class="px-5 col-md-8">
                    <label asp-for="Trip.Name" class="form-label mt-4"></label>
                    <span asp-validation-for="Trip.Name" class="text-danger"></span>
                    <input asp-for="@Model.Trip.Name" class="form-control" />
                </div>
            </div>
            <div class=" d-flex justify-content-center">
                <div class="px-5 col-md-8">
                    <label asp-for="Trip.Description" class="form-label mt-4"></label>
                    <span asp-validation-for="Trip.Description" class="text-danger"></span>
                    <textarea asp-for="@Model.Trip.Description" class="form-control"></textarea>
                </div>
            </div>
            <div class="d-flex justify-content-around  py-5">
                <div class="row row-cols-1 row-cols-md-4">
                    <input asp-for="@Model.Tags" type="hidden" />
                    @foreach (var item in Model.Tags)
                    {
                        <div class="col py-2">
                            <input asp-for="@item.IsSelected" type="checkbox" />
                            <input asp-for="@item.TagName" type="hidden" />
                            <input asp-for="@item.TagId" type="hidden" />
                            <label class="form-label mt-4">@item.TagName</label>
                        </div>
                    }
                </div>
            </div>
            <hr class="my-5" />
            <div class="row pt-2">
                <div class="col-12 col-md-3">
                    <button type="submit" class="btn btn-primary form-control">Create</button>
                </div>
                <div class="col-12 col-md-3">
                    <a asp-controller="Trip" asp-action="Index" class="btn btn-outline-primary border  form-control">
                        Back to List
                    </a>
                </div>
            </div>
        </form>
    </div>
</div>

@section Scripts{
    @{
        <partial name="_ValidationScriptsPartial" />
    }
}

一切正常工作,唯一的问题是我没有将 SelectTagViewModel 列表发送回服务器。

我知道这可能是一个愚蠢的错误,但我已经试图找出为什么不工作了几个小时了,我赶时间。

提前感谢您的任何答案! 为什么我的视图模型属性没有发送回服务器?

英文:

ASP.NET Core 7 MVC - view model's property is not being sent back to the server.

I have two entities that have a many-to-many relationship between them:

public class Trip
{
[Key]
public Guid TripId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
[ValidateNever]
public IEnumerable&lt;Tag&gt; Tags { get; set; }
}
public class Tag
{
[Key]
public Guid TagId { get; set; }
public string Name { get; set; }
[ValidateNever]
public IEnumerable&lt;Trip&gt; Trips { get; set; }
}

When I create a new Trip, I want to be able to select multiple tags using checkboxes. For this I created two view models:

public class SelectTagViewModel
{
public string TagId { get; set; }
public string TagName { get; set; }
public bool IsSelected { get; set; } = false;
}
public class CreateTripViewModel
{
public Trip Trip { get; set; }
[ValidateNever]
public List&lt;SelectTagViewModel&gt; Tags { get; set; }
}

This is the controller:

public class TripController : Controller
{
private readonly ITripRepository _tripRepository;
private readonly ITagRepository _tagRepository;
public TripController(ITripRepository tripRepository, ITagRepository tagRepository)
{
_tripRepository = tripRepository;
_tagRepository = tagRepository;
}
public async Task&lt;IActionResult&gt; Index()
{
var trips = await _tripRepository.GetAllTripsAsync(null, &quot;Tags&quot;);
return View(trips);
}
public async Task&lt;IActionResult&gt; Create()
{
List&lt;SelectTagViewModel&gt; tagsList = (await _tagRepository.GetAllTagsAsync(null)).Select(
u =&gt; new SelectTagViewModel
{
TagId = u.TagId.ToString(),
TagName = u.Name
}).ToList();
CreateTripViewModel viewModel = new()
{
Trip = new(),
Tags = tagsList
};
return View(viewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task&lt;IActionResult&gt; Create(CreateTripViewModel createTripViewModel)
{
if (ModelState.IsValid)
{
await _tripRepository.AddTripAsync(createTripViewModel.Trip);
return RedirectToAction(nameof(Index));
}
return View(createTripViewModel);
}
}

And this is the Create action's view:

@using TestApplication.ViewModels;
@model CreateTripViewModel
&lt;div class=&quot;card shadow border-0 mt-4&quot; style=&quot;margin-left:20vw; margin-right:20vw;&quot;&gt;
&lt;div class=&quot;card-header bg-primary m-lg-0 py-3&quot;&gt;
&lt;div class=&quot;row&quot;&gt;
&lt;div class=&quot;col-12 text-center&quot;&gt;
&lt;h2 class=&quot;text-white py-2&quot;&gt;Create Trip&lt;/h2&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;card-body p-4&quot;&gt;
&lt;form method=&quot;post&quot; class=&quot;row px-5&quot; asp-action=&quot;Create&quot;&gt;
&lt;div class=&quot; d-flex justify-content-center&quot;&gt;
&lt;div class=&quot;px-5 col-md-8&quot;&gt;
&lt;label asp-for=&quot;Trip.Name&quot; class=&quot;form-label mt-4&quot;&gt;&lt;/label&gt;
&lt;span asp-validation-for=&quot;Trip.Name&quot; class=&quot;text-danger&quot;&gt;&lt;/span&gt;
&lt;input asp-for=&quot;@Model.Trip.Name&quot; class=&quot;form-control&quot; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot; d-flex justify-content-center&quot;&gt;
&lt;div class=&quot;px-5 col-md-8&quot;&gt;
&lt;label asp-for=&quot;Trip.Description&quot; class=&quot;form-label mt-4&quot;&gt;&lt;/label&gt;
&lt;span asp-validation-for=&quot;Trip.Description&quot; class=&quot;text-danger&quot;&gt;&lt;/span&gt;
&lt;textarea asp-for=&quot;@Model.Trip.Description&quot; class=&quot;form-control&quot;&gt;&lt;/textarea&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;d-flex justify-content-around  py-5&quot;&gt;
&lt;div class=&quot;row row-cols-1 row-cols-md-4&quot;&gt;
&lt;input asp-for=&quot;@Model.Tags&quot; type=&quot;hidden&quot; /&gt;
@foreach (var item in Model.Tags)
{
&lt;div class=&quot;col py-2&quot;&gt;
&lt;input asp-for=&quot;@item.IsSelected&quot; type=&quot;checkbox&quot; /&gt;
&lt;input asp-for=&quot;@item.TagName&quot; type=&quot;hidden&quot; /&gt;
&lt;input asp-for=&quot;@item.TagId&quot; type=&quot;hidden&quot; /&gt;
&lt;label class=&quot;form-label mt-4&quot;&gt;@item.TagName&lt;/label&gt;
&lt;/div&gt;
}
&lt;/div&gt;
&lt;/div&gt;
&lt;hr class=&quot;my-5&quot; /&gt;
&lt;div class=&quot;row pt-2&quot;&gt;
&lt;div class=&quot;col-12 col-md-3&quot;&gt;
&lt;button type=&quot;submit&quot; class=&quot;btn btn-primary form-control&quot;&gt;Create&lt;/button&gt;
&lt;/div&gt;
&lt;div class=&quot;col-12 col-md-3&quot;&gt;
&lt;a asp-controller=&quot;Trip&quot; asp-action=&quot;Index&quot; class=&quot;btn btn-outline-primary border  form-control&quot;&gt;
Back to List
&lt;/a&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;/div&gt;
@section Scripts{
@{
&lt;partial name=&quot;_ValidationScriptsPartial&quot; /&gt;
}
}

Everything works fine, the only problem is that I don't get the SelectTagViewModel list back to the server.

I know that it's probably a silly mistake, but I've been trying to figure out why it doesn't work for hours and I'm in a rush.

Thank you for any answers in advance! 为什么我的视图模型属性没有发送回服务器?

答案1

得分: 0

这是我的使用方式。

查看代码:

<div class="form-group">
    <label asp-for="Input.JuryApplicationViewModel.Expertise" class="form-label"></label>
    <ul class="custom-control-group g-3 align-center">
        @foreach (var item in Model.Input.CategorySelectList)
        {
            <li>
                <div class="custom-control custom-control-sm custom-checkbox">
                    <input type="checkbox" class="custom-control-input" name="Input.JuryApplicationViewModel.Expertise" id="@item.Value" value="@item.Value" @(item.Selected ? "checked" : "")>
                    <label class="custom-control-label" for="@item.Value">@item.Text</label>
                </div>
            </li>
        }
    </ul>
</div>

控制器代码:

public class InputModel
{
    public InputModel()
    {
        this.CategorySelectList = new List<SelectListItem>();
        this.JuryApplicationViewModel = new JuryApplicationViewModel();
        this.OperationType = OperationTypeEnum.Add;
        this.Result = null;
        this.ReferrerUri = String.Empty;
    }

    // 用于显示类别的属性
    public List<SelectListItem> CategorySelectList { get; set; }

    public JuryApplicationViewModel JuryApplicationViewModel { get; set; }

    public OperationTypeEnum OperationType { get; set; }

    public Result? Result { get; set; }

    public string ReferrerUri { get; set; }
}
英文:

This is how i use.

View code:

&lt;div class=&quot;form-group&quot;&gt;
&lt;label asp-for=&quot;Input.JuryApplicationViewModel.Expertise&quot; class=&quot;form-label&quot;&gt;&lt;/label&gt;
&lt;ul class=&quot;custom-control-group g-3 align-center&quot;&gt;
@foreach (var item in Model.Input.CategorySelectList)
{
&lt;li&gt;
&lt;div class=&quot;custom-control custom-control-sm custom-checkbox&quot;&gt;
&lt;input type=&quot;checkbox&quot; class=&quot;custom-control-input&quot; name=&quot;Input.JuryApplicationViewModel.Expertise&quot; id=&quot;@item.Value&quot; value=&quot;@item.Value&quot; @(item.Selected ? &quot;checked&quot; : &quot;&quot;)&gt;
&lt;label class=&quot;custom-control-label&quot; for=&quot;@item.Value&quot;&gt;@item.Text&lt;/label&gt;
&lt;/div&gt;
&lt;/li&gt;
}
&lt;/ul&gt;
&lt;/div&gt;  

Controller code

public class InputModel
{
public InputModel()
{
this.CategorySelectList = new List&lt;SelectListItem&gt;();
this.JuryApplicationViewModel = new JuryApplicationViewModel();
this.OperationType = OperationTypeEnum.Add;
this.Result = null;
this.ReferrerUri = String.Empty;
}
// property for displaying categories
public List&lt;SelectListItem&gt; CategorySelectList { get; set; }
public JuryApplicationViewModel JuryApplicationViewModel { get; set; }
public OperationTypeEnum OperationType { get; set; }
public Result? Result { get; set; }
public string ReferrerUri { get; set; }
}

答案2

得分: 0

你只需要更改视图部分中的For循环。

这是正确的代码:

@* <input asp-for="@Model.Tags" type="hidden" /> *@
@for (int i = 0; i < Model.Tags.Count; i++)
{
    <div class="col py-2">
        <input asp-for="@Model.Tags[i].IsSelected" type="checkbox" />
        <input asp-for="@Model.Tags[i].TagName" type="hidden" />
        <input asp-for="@Model.Tags[i].TagId" type="hidden" />
        <label class="form-label mt-4">@Model.Tags[i].TagName</label>
    </div>
}

你的代码(这段代码是错误的):

<input asp-for="@Model.Tags" type="hidden" />
@foreach (var item in Model.Tags)
{
    <div class="col py-2">
        <input asp-for="@item.IsSelected" type="checkbox" />
        <input asp-for="@item.TagName" type="hidden" />
        <input asp-for="@item.TagId" type="hidden" />
        <label class="form-label mt-4">@item.TagName</label>
    </div>
}
英文:

You just need to change your For in the view section

This is Correct Code

 @* &lt;input asp-for=&quot;@Model.Tags&quot; type=&quot;hidden&quot; /&gt;*@
@for (int i = 0; i &lt; Model.Tags.Count;i++)
{
&lt;div class=&quot;col py-2&quot;&gt;
&lt;input asp-for=&quot;@Model.Tags[i].IsSelected&quot; type=&quot;checkbox&quot; /&gt;
&lt;input asp-for=&quot;@Model.Tags[i].TagName&quot; type=&quot;hidden&quot; /&gt;
&lt;input asp-for=&quot;@Model.Tags[i].TagId&quot; type=&quot;hidden&quot; /&gt;
&lt;label class=&quot;form-label mt-4&quot;&gt;@Model.Tags[i].TagName&lt;/label&gt;
&lt;/div&gt;
}

Your code(This code is wrong)

       &lt;input asp-for=&quot;@Model.Tags&quot; type=&quot;hidden&quot; /&gt;
@foreach (var item in Model.Tags)
{
&lt;div class=&quot;col py-2&quot;&gt;
&lt;input asp-for=&quot;@item.IsSelected&quot; type=&quot;checkbox&quot; /&gt;
&lt;input asp-for=&quot;@item.TagName&quot; type=&quot;hidden&quot; /&gt;
&lt;input asp-for=&quot;@item.TagId&quot; type=&quot;hidden&quot; /&gt;
&lt;label class=&quot;form-label mt-4&quot;&gt;@item.TagName&lt;/label&gt;
&lt;/div&gt;
}

huangapple
  • 本文由 发表于 2023年5月29日 02:22:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76352984.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定