如何通过Get请求使绑定对附加参数起作用

时间:2019-09-06 20:04:36

标签: binding asp.net-core-mvc

我的模型具有属性

public int SelectedContactId { get; set; }

视图有一个下拉菜单,更改选择后会刷新视图:

<select asp-for="SelectedContactId" 
    asp-items="Model.Contacts" 
    class="form-control ddlContractorContacts bg-light" 
    onchange="location.reload(true)">
</select>

HttpGet Edit()操作方法称为:

// GET: Contractors/Edit/5
public ActionResult Edit(int? contractorId, int SelectedContactId)

但是SelectedContactId不受限制,我不知道该怎么做。

P.S。如果我在[FromBody]之前使用int SelectedContactId属性,则在第一次加载页面时会收到错误消息:HTTP错误415。

2 个答案:

答案 0 :(得分:1)

首先,阅读您的评论

// GET: Contractors/Edit/5
public ActionResult Edit(int? contractorId, int SelectedContactId)

它看起来像承包商ID是5,并且由于您正在编辑承包商,URL始终存在。所以您应该将其更改为

// GET: Contractors/Edit/5
public ActionResult Edit(int Id, int SelectedContactId)

要利用MVC默认路由映射-/后面的整数应自动绑定到Id


然后我认为您的SelectedContactId应该标记为可选项,因为当您首次进入编辑页面时,不应有任何选定的联系人。并且您希望用户选择联系人后立即将所选联系人自动绑定为URL上的其他参数。那就是你想正确完成的事情?

在这种情况下,应将SelectedContactId更改为可选:

// GET: Contractors/Edit/5
public ActionResult Edit(int Id, int? SelectedContactId)


现在让我们来谈谈重点。有许多方法可以操纵查询参数。其中一些是:

  1. 提交GET表单
  2. 使用JavaScript将输入手动添加到URL

在这里,我向您展示#1-提交GET表单。


提交GET表单

如果希望服务器在视图上获得输入选择,则需要提交包含所有输入的<form />

每当用户进行选择并单击“提交”按钮时,表单就会将输入数据发送回服务器。然后,您的MVC会将请求绑定到操作的参数。

使用 JavaScript location.reload(true)仅刷新当前页面。它不会将输入发送回服务器。

查看模型

public class EditContractorViewModel
{
    [Display(Name = "Contact")]
    public int? SelectedContactId { get; set; }

    public IEnumerable<SelectListItem> Contacts { get; set; }
}

控制器

public class ContractorController : Controller
{
    public IActionResult Edit(int id, int? selectedContactId)
    {
        // In theory, you need to take the id and look that up in your persistent storage
        // and then you build up the view model and pass it back to the View

        var vm = new EditContractorViewModel
        {
            SelectedContactId = selectedContactId,
            Contacts = new List<SelectListItem>
            {
                new SelectListItem("Contact 1", "1"),
                new SelectListItem("Contact 2", "2"),
                new SelectListItem("Contact 3", "3"),
                new SelectListItem("Contact 4", "4"),
                new SelectListItem("Contact 5", "5")
            }
        };

        return View(vm);
    }
}

查看

<!-- The View -->
@model EditContractorViewModel

<form asp-area="" asp-controller="ContractorController" asp-action="Edit"
    method="get">
    <div class="form-group">
        <label asp-for="SelectedContactId"></label>
        <select asp-for="SelectedContactId" 
            asp-items="Model.Contacts" 
            class="form-control ddlContractorContacts bg-light">
            <option value="">- select -</option>
        </select>
    </div>
    <button type="submit" class="btn btn-success">Submit</button>
</form>

结果

首次登陆页面:

enter image description here

选择一个联系人并点击“提交”:

enter image description here

如果您希望表单在下拉更改时自动提交,则可以摆脱视图上的“提交”按钮,并编写一些 JavaScript 来手动提交表单:

$(function() {
    $('select.ddlContractorContacts').change(function() {
        let $form = $(this).closest('form');

        $form.submit();

        return false;
    });
});

答案 1 :(得分:1)

由于您使用location.reload(true),它将始终重定向到/Contractors/Edit/5,并且您在编辑操作上的SelectedContactId始终为0,因为您没有在查询字符串或其他地方传递所选的ID

一种简单的方法是,您可以使用/Contractors/Edit/5?SelectedContactId=1之类的查询字符串来传递ID。

请参阅下面的视图代码:

<select asp-for="SelectedContactId"
        asp-items="Model.Contacts"
        id="mySelectedContactId"
        class="form-control ddlContractorContacts bg-light"
        onchange="reload()"></select>

@section  Scripts{ 
<script>
    function reload() {
        var selectedContactId = document.getElementById("mySelectedContactId").value;
        var url = window.location.href.split(/[?#]/)[0];    

        url += '?SelectedContactId=' + selectedContactId

        window.location.href = url;
     }
</script>
}