英文:
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<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; }
}
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<SelectTagViewModel> 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<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);
}
}
And this is the Create
action's view:
@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" />
}
}
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:
<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>
Controller code
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;
}
// property for displaying categories
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; }
}
答案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
@* <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>
}
Your code(This code is wrong)
<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>
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论