View 获取从视图选择回控制器的选定选项

View 获取从视图选择回控制器的选定选项,view,controller,asp.net-core-mvc,viewmodel,View,Controller,Asp.net Core Mvc,Viewmodel,我有一个ASP.NETCore1.1MVCWeb应用程序。该应用程序与web API后端对话,以向数据存储读取/写入数据 在web应用程序中,我有一个编辑页面,您可以在其中编辑特定对象的记录。记录中的一个字段是dropdownlist,即HTML标记。我的问题是,我不知道如何从视图中的dropdownlist将所选选项返回控制器 为了向您简要介绍背景,房地产代理将使用此web应用程序管理其物业。简单地说,目前房产有一个基本结构——身份证、地址和房产类型房屋、公寓、办公室等 所以我有两个模型: u

我有一个ASP.NETCore1.1MVCWeb应用程序。该应用程序与web API后端对话,以向数据存储读取/写入数据

在web应用程序中,我有一个编辑页面,您可以在其中编辑特定对象的记录。记录中的一个字段是dropdownlist,即HTML标记。我的问题是,我不知道如何从视图中的dropdownlist将所选选项返回控制器

为了向您简要介绍背景,房地产代理将使用此web应用程序管理其物业。简单地说,目前房产有一个基本结构——身份证、地址和房产类型房屋、公寓、办公室等

所以我有两个模型:

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.
    }
}

然后,我创建了一个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");
        }
@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");}
}
然后我有一个填充视图的控制器:

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");
        }
@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");}
}
我知道对API进行两次调用是低效的——一次是获取属性,另一次是获取属性类型列表——我稍后会对此进行改进,但现在情况就是这样。。。 以及以下观点:

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");
        }
@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();
            }
        }
因此,此控制器操作将更新的属性发布到web API。问题是,在最终控制器操作之前,一切都是100%工作的-如果我检查prop参数,它包含所有修改,但不包含所选的PopertyType-我如何将所选的PropertyType从视图返回控制器? 谢谢


谢谢你,mvermef