将 SELECT 的选定选项从视图返回到控制器
Getting selected option of SELECT from View back to Controller
我有一个 ASP .Net Core 1.1 MVC 网络应用程序。该应用程序与 Web API 后端对话,将 read/write 数据传输到数据存储。
在网络应用程序中,我有一个编辑页面,您可以在其中编辑特定对象的记录。记录中的字段之一是下拉列表(即 HTML 标签)。我的问题是我不知道如何从下拉列表(在视图中)中将选定的选项返回给控制器。
为了简要介绍背景,房地产经纪人将使用此 Web 应用程序来管理他们的财产。简单来说,现在 属性 有一个基本结构 - 一个 ID、地址和一个 "Property Type"(房子、公寓、办公室等)
所以我有这两个模型:
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace InspectionsData.Models
{
public partial class PropertyType
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string PropertyTypeName { get; set; } // e.g. house, flat, office, etc.
}
}
和
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace InspectionsData.Models
{
[Table("property")]
public class Property
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int? Id { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string Region { get; set; }
public string Country { get; set; }
public int? PropertyTypeId { get; set; }
[ForeignKey("PropertyTypeId")]
public PropertyType PropertyType { get; set; }
}
}
然后我创建了一个 ViewModel,这样我就可以将上述两个模型都提供给视图:
using InspectionsData.Models;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace InspectionsTestClient.ViewModels
{
public class PropertyIndexViewModel
{
public Property Property { get; set; }
public SelectList PropertyTypes { get; set; }
}
}
然后我有一个填充视图的控制器:
// GET: Property/Edit/5
public async Task<ActionResult> Edit(int id)
{
string apiUrl = "http://localhost:50082/api/";
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
//Read property from Web API
string url = apiUrl + "Properties/" + id.ToString();
HttpResponseMessage responseMessage = await client.GetAsync(url);
if (responseMessage.IsSuccessStatusCode)
{
var responseData = responseMessage.Content.ReadAsStringAsync().Result;
var prop = Newtonsoft.Json.JsonConvert.DeserializeObject<Property>(responseData);
if (prop == null)
{
return NotFound();
}
List<PropertyType> propertyTypes = null;
url = apiUrl + "PropertyTypes";
responseMessage = await client.GetAsync(url);
if (responseMessage.IsSuccessStatusCode)
{
responseData = responseMessage.Content.ReadAsStringAsync().Result;
propertyTypes = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PropertyType>>(responseData);
}
PropertyIndexViewModel vm = new PropertyIndexViewModel()
{
Property = prop,
PropertyTypes = new SelectList(propertyTypes, "Id", "PropertyTypeName")
};
return View(vm);
}
return View("Error");
}
我知道对 API 进行两次调用效率低下 - 一次获取 属性 ,一次获取 属性 类型的列表 - 我稍后会对此进行改进,但现在就是这样......
和视图:
@model InspectionsTestClient.ViewModels.PropertyIndexViewModel
@{
ViewData["Title"] = "Edit";
}
@{
Layout = "_Layout";
}
<h2>Edit</h2>
@Html.ValidationSummary();
<form asp-action="Edit">
<div class="form-horizontal">
<h4>Property</h4>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Property.Id" />
<div class="form-group">
<label asp-for="Property.Street" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Property.Street" class="form-control" />
<span asp-validation-for="Property.Street" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Property.City" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Property.City" class="form-control" />
<span asp-validation-for="Property.City" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Property.Region" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Property.Region" class="form-control" />
<span asp-validation-for="Property.Region" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Property.Country" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Property.Country" class="form-control" />
<span asp-validation-for="Property.Country" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Property.PropertyType" class="col-md-2 control-label"></label>
<div class="col-md-10">
<select asp-for="Property.PropertyType" asp-items="@Model.PropertyTypes"></select>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
</form>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
当用户单击表单上的“保存”按钮时,它回传到另一个控制器操作:
// POST: Property/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(int id, Property prop)
{
try
{
if (ModelState.IsValid)
{
string apiUrl = "http://localhost:50082/api/";
string url = apiUrl + "properties/" + id.ToString();
string jsonInString = JsonConvert.SerializeObject(prop);
HttpContent content = new StringContent(jsonInString, Encoding.UTF8, "application/json");
HttpResponseMessage responseMessage = await client.PutAsync(url, content);
if (responseMessage.IsSuccessStatusCode)
{
return RedirectToAction("Index");
}
}
return View();
}
catch
{
return View();
}
}
因此此控制器操作将更新后的 属性 发布到网络 API。问题是,一切都 100% 工作,直到它到达这个最终的控制器操作 - 如果我检查 "prop" 参数,它包含所做的所有修改,但它不包含选定的 PopertyType - 我怎么能 return 所选择的 属性 从视图类型返回到控制器?
谢谢...
//json result...
public async Task<ActionResult> Edit(int id, [FromBody]Property prop)
{
https://andrewlock.net/model-binding-json-posts-in-asp-net-core/
我有一个 ASP .Net Core 1.1 MVC 网络应用程序。该应用程序与 Web API 后端对话,将 read/write 数据传输到数据存储。
在网络应用程序中,我有一个编辑页面,您可以在其中编辑特定对象的记录。记录中的字段之一是下拉列表(即 HTML 标签)。我的问题是我不知道如何从下拉列表(在视图中)中将选定的选项返回给控制器。
为了简要介绍背景,房地产经纪人将使用此 Web 应用程序来管理他们的财产。简单来说,现在 属性 有一个基本结构 - 一个 ID、地址和一个 "Property Type"(房子、公寓、办公室等)
所以我有这两个模型:
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace InspectionsData.Models
{
public partial class PropertyType
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string PropertyTypeName { get; set; } // e.g. house, flat, office, etc.
}
}
和
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace InspectionsData.Models
{
[Table("property")]
public class Property
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int? Id { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string Region { get; set; }
public string Country { get; set; }
public int? PropertyTypeId { get; set; }
[ForeignKey("PropertyTypeId")]
public PropertyType PropertyType { get; set; }
}
}
然后我创建了一个 ViewModel,这样我就可以将上述两个模型都提供给视图:
using InspectionsData.Models;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace InspectionsTestClient.ViewModels
{
public class PropertyIndexViewModel
{
public Property Property { get; set; }
public SelectList PropertyTypes { get; set; }
}
}
然后我有一个填充视图的控制器:
// GET: Property/Edit/5
public async Task<ActionResult> Edit(int id)
{
string apiUrl = "http://localhost:50082/api/";
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
//Read property from Web API
string url = apiUrl + "Properties/" + id.ToString();
HttpResponseMessage responseMessage = await client.GetAsync(url);
if (responseMessage.IsSuccessStatusCode)
{
var responseData = responseMessage.Content.ReadAsStringAsync().Result;
var prop = Newtonsoft.Json.JsonConvert.DeserializeObject<Property>(responseData);
if (prop == null)
{
return NotFound();
}
List<PropertyType> propertyTypes = null;
url = apiUrl + "PropertyTypes";
responseMessage = await client.GetAsync(url);
if (responseMessage.IsSuccessStatusCode)
{
responseData = responseMessage.Content.ReadAsStringAsync().Result;
propertyTypes = Newtonsoft.Json.JsonConvert.DeserializeObject<List<PropertyType>>(responseData);
}
PropertyIndexViewModel vm = new PropertyIndexViewModel()
{
Property = prop,
PropertyTypes = new SelectList(propertyTypes, "Id", "PropertyTypeName")
};
return View(vm);
}
return View("Error");
}
我知道对 API 进行两次调用效率低下 - 一次获取 属性 ,一次获取 属性 类型的列表 - 我稍后会对此进行改进,但现在就是这样...... 和视图:
@model InspectionsTestClient.ViewModels.PropertyIndexViewModel
@{
ViewData["Title"] = "Edit";
}
@{
Layout = "_Layout";
}
<h2>Edit</h2>
@Html.ValidationSummary();
<form asp-action="Edit">
<div class="form-horizontal">
<h4>Property</h4>
<hr />
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Property.Id" />
<div class="form-group">
<label asp-for="Property.Street" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Property.Street" class="form-control" />
<span asp-validation-for="Property.Street" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Property.City" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Property.City" class="form-control" />
<span asp-validation-for="Property.City" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Property.Region" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Property.Region" class="form-control" />
<span asp-validation-for="Property.Region" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Property.Country" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="Property.Country" class="form-control" />
<span asp-validation-for="Property.Country" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="Property.PropertyType" class="col-md-2 control-label"></label>
<div class="col-md-10">
<select asp-for="Property.PropertyType" asp-items="@Model.PropertyTypes"></select>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
</form>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
当用户单击表单上的“保存”按钮时,它回传到另一个控制器操作:
// POST: Property/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit(int id, Property prop)
{
try
{
if (ModelState.IsValid)
{
string apiUrl = "http://localhost:50082/api/";
string url = apiUrl + "properties/" + id.ToString();
string jsonInString = JsonConvert.SerializeObject(prop);
HttpContent content = new StringContent(jsonInString, Encoding.UTF8, "application/json");
HttpResponseMessage responseMessage = await client.PutAsync(url, content);
if (responseMessage.IsSuccessStatusCode)
{
return RedirectToAction("Index");
}
}
return View();
}
catch
{
return View();
}
}
因此此控制器操作将更新后的 属性 发布到网络 API。问题是,一切都 100% 工作,直到它到达这个最终的控制器操作 - 如果我检查 "prop" 参数,它包含所做的所有修改,但它不包含选定的 PopertyType - 我怎么能 return 所选择的 属性 从视图类型返回到控制器? 谢谢...
//json result...
public async Task<ActionResult> Edit(int id, [FromBody]Property prop)
{
https://andrewlock.net/model-binding-json-posts-in-asp-net-core/