2016-09-16 74 views
0

我有一個強類型的Razor視圖,它顯示了一個類的記錄。該視圖顯示用戶可用來更新記錄的表單(下拉菜單,幾個複選框和幾個文本框)。當用戶通過更改控件的值來修改字段時,會立即將ajax調用發送到Web API以更新該字段。下面的Ajax調用工作正常:Web API的序列化表單數據API請求MVC 5

$(document).ready(function() { 
    $(this).on("change", function (e) { 
     var editRecordURL = $("#editRecordURL").val(); 
     var key = $("#AccessVM_Id").val(); 
     var mode = $("#AccessVM_AccessMode").val(); 
     var failLim = $("#AccessVM_LoginFailLimit").val(); 
     var cap = $("#AccessVM_PwdWCap").is(':checked'); 
     ... 
     var rec = { 
      Id: key, 
      AccessMode: mode, 
      LoginFailLimit: failLim, 
      PwdWCap: cap, 
      .... 
     }; 

     $.ajax({ 
      type: "PUT", 
      url: editRecordURL, 
      data: JSON.stringify(rec), 
      contentType: 'application/json; charset=utf-8', 
      success: function (msg) { 
       bootbox.alert("Success: Record updated successfully!"); 
      }, 
      error: function (XMLHttpRequest, textStatus, errorThrown) { 
       bootbox.alert("Error: " + errorThrown); 
      } 
     }); 
    }); 
}); 

不過,我想使這一功能更通用的,因此它可再用於其他形式(尤其是那些擁有更多的數據來更新)。理想情況下,拍攝對象將被填充這樣的:

var rec = $("#form").serializeArray(); 

不幸的是,這並不因爲應用JSON.stringify()rec它不會返回預期的JSON字符串後的工作。相反,它發出這樣一個系列的名稱/值對:

[{"name":"__RequestVerificationToken","value":"qVedWHJ6HIrqtLJpTxp4m5D2ehZ_AdjCOvQtz4Jyzlg0cdocsWqcTCiE2jzIEB7UsJPwuSZeZF7y1GsluHNrNCDV1wrHjU1UJO5vMMGTLB41"},{"name":"AccessVM.Id","value":"1"},{"name":"AccessVM.AccessMode","value":"1"},{"name":"AccessVM.LoginFailLimit","value":"10"},{"name":"AccessVM.PwdWCap","value":"true"},{"name":"AccessVM.PwdWCap","value":"false"},{"name":"AccessVM.PwdWNum","value":"true"},{"name":"AccessVM.PwdWNum","value":"false"},{"name":"AccessVM.PwdWSC","value":"true"},{"name":"AccessVM.PwdWSC","value":"false"},{"name":"AccessVM.PwdMinLen","value":"6"},{"name":"AccessVM.PwdMaxLen","value":"25"},{"name":"AccessVM.PwdChange","value":"90"},{"name":"AccessVM.PwdPrevUsedLimit","value":"10"}] 

那麼,如何解決這個問題因此字符串的樣子:

[{"AccessVM.Id": 1, "AccessVM.AccessMode": 1, "AccessVM.LoginFailLimit": 10, "AccessVM.PwdWCap": true, "AccessVM.PwdWNum": true, "AccessVM.PwdWSC": false, "AccessVM.PwdMinLen": 6, "AccessVM.PwdMaxLen": 25, "AccessVM.PwdChange": 90, "AccessVM.PwdPrevUsedLimit": 10}] 

的Web API控制器:

public class PoliciesController : ApiController 
{ 
    .... 
    // PUT: api/policies/1 
    [ResponseType(typeof(void))] 
    public IHttpActionResult PutPolicy(int id, AccessItemViewModel polDto) 
    { 
     .... 
    } 
    .... 
} 

查看車型

public class PolicyViewModel 
{ 
    public AccessItemViewModel AccessVM { get; set; } 
    .... 
} 

public class AccessItemViewModel 
{ 
    public int Id { get; set; } 
    public int AccessMode { get; set; } 
    public int LoginFailLimit { get; set; } 
    public bool PwdWCap { get; set; } 
    .... 
} 

Razor視圖:

@model App.Web.ViewModels.PolicyViewModel 
.... 
@using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 
{ 
    @Html.AntiForgeryToken() 
    @Html.ValidationSummary("", new { @class = "text-danger" }) 
    <input type="hidden" id="editRecordURL" value="@Model.ExtraVM.EditRecordUrl" /> 
    @Html.LabelFor(m => m.AccessVM.AccessMode, new { @class = "col-xs-5" }) 
    @Html.HiddenFor(m => m.AccessVM.Id) 
    @Html.DropDownListFor(m => m.AccessVM.AccessMode, new SelectList(Model.AccessModes, "Mode", "Description"), null, new { @class = "input-sm col-xs-7" }) 
    @Html.LabelFor(m => m.AccessVM.LoginFailLimit, new { @class = "col-xs-9" }) 
    @Html.DropDownListFor(m => m.AccessVM.LoginFailLimit, new SelectList(Model.LoginLimits, "LoginFailLimit", "Value"), null, new { @class = "input-sm col-xs-3" }) 
    @Html.LabelFor(m => m.AccessVM.PwdWCap, new { @class = "col-xs-11" }) 
    @Html.CheckBoxFor(m => m.AccessVM.PwdWCap, new { @class = "input-xs col-xs-1" }) 
    .... 
} 
+0

這是'$( 「#形式」)。序列化()'(不' .serializeArray()')並移除'contentType:'application/json; charset = utf-8','不要stringify(只使用'data:$(「#form」)。serialize(),') –

+0

這不起作用(我得到錯誤「未找到」),因爲它創建一個查詢字符串的鍵值如下:AccessVM.Id = 1&AccessVM.AccessMode = 1&AccessVM.LoginFailLimit = 1&AccessVM.PwdWCap = false&AccessVM.PwdWNum = false&AccessVM.PwdWSC = false&AccessVM。PwdMinLen = 3 ... Web API端點需要發送一個類型爲「policy」的對象(這意味着一個JSON對象)。但是如果我能以某種方式把這個字符串變成一個JSON對象,那將是非常棒的! –

+0

你是什麼'政策'模型。如果它包含一個名爲'AccessVM'的複雜屬性,它包含'Id','AccessMode'等屬性,它會很好地綁定。並顯示部分視圖和控制器(根據您說的正確的話,那麼POST方法中的模型與視圖中的模型不同(它應該是這樣) –

回答

1

您將需要使用.serialize()(不.serializeArray()它不會與你bool性能和DefaultModelBinder正常工作),所以它使用默認application/x-www-form-urlencoded; charset=UTF-8,不字符串化數據刪除contentType選項。夜腳本應該

$.ajax({ 
    type: "PUT", 
    url: editRecordURL, 
    data: $('form').serialize(), 
    success: function (msg) { 

然而在視圖模型是PolicyViewModel,並基於該模型的生成表單控件,所以.serialize()函數會序列名稱/值對的PolicyViewModel。這意味着您的PutPolicy方法中的模型必須匹配。該方法需要將

public IHttpActionResult PutPolicy(int id, PolicyViewModel model) // not AccessItemViewModel 

如果方法參數不能改變,那麼你的視圖需要根據AccessItemViewModel或者你需要讓你產生'名使用的局部視圖爲AccessVM財產沒有「AccessVM」前綴的屬性。例如

_AccessVM.cshtml

@model AccessItemViewModel 
@Html.HiddenFor(m => m.Id) 
.... 

,並在主視圖中,使用@Html.Action()@Html.Partial()生成它的HTML