MVC3 & JSON.stringify() ModelBinding 返回空模型

Posted

技术标签:

【中文标题】MVC3 & JSON.stringify() ModelBinding 返回空模型【英文标题】:MVC3 & JSON.stringify() ModelBinding returns null model 【发布时间】:2011-11-27 17:07:37 【问题描述】:

我正在尝试使用 MVC3 和 JSON 进行模型绑定,但我没有运气...无论我做什么,我似乎都在服务器上获得了 null 模型。

方法签名:

public ActionResult FilterReports(DealSummaryComparisonViewModel model)

javascript 更新

<script type="text/javascript" language="javascript">

    $(document).ready(function () 
        $('#filter-reports').click(filterReports);
    );

    function filterReports() 
        var filters = 
            SelectedRtoId: $('#SelectedRtoId').val(),
            SelectedPricingPointId: $('#SelectedPricingPointId').val(),
            SelectedLoadTypeId: $('#SelectedLoadTypeId').val(),
            SelectedBlockId: $('#SelectedBlockId').val(),
            SelectedRevisionStatusId: $('#SelectedRevisionStatusId').val()
        
        var dealSummaries =  SelectedItemIds: $('#SelectedItemIds').val() 
        var model =  ReportingFilters: filters, DealSummaries: dealSummaries 

        $('#selected-items select option').attr("selected", "selected");
        $.ajax(
            url: '@Url.Action("FilterReports")',
            data: model,
            contentType: 'application/json',
            dataType: 'json',
            success: function (data) 
                alert(data);
            
        ); 
    
</script>

型号:

public class DealSummaryComparisonViewModel

    public ReportingFiltersViewModel ReportingFilters  get; set; 
    public LadderListViewModel DealSummaries  get; set; 


public class LadderListViewModel

    public MultiSelectList AvailableItems  get; set; 

    public int[] SelectedItemIds  get; set; 
    public MultiSelectList SelectedItems  get; set; 


public class ReportingFiltersViewModel

    public int? SelectedRtoId  get; set; 
    public ICollection<Rto> Rtos  get; set; 

    public int? SelectedPricingPointId  get; set; 
    public ICollection<PricingPoint> PricingPoints  get; set; 

    public int? SelectedLoadTypeId  get; set; 
    public ICollection<LoadType> LoadTypes  get; set; 

    public int? SelectedBlockId  get; set; 
    public ICollection<Block> Blocks  get; set; 

    public int? SelectedRevisionStatusId  get; set; 
    public ICollection<RevisionStatus> RevisionStatuses  get; set; 

    public bool? DealStatus  get; set; 

模型在客户端看起来不错:

"ReportingFilters":
    "SelectedRtoId":"5",
    "SelectedPricingPointId":"20",
    "SelectedLoadTypeId":"55",
    "SelectedBlockId":"21",
    "SelectedRevisionStatusId":"11" 
,"DealSummaries":
    "SelectedItemIds":["21","22","23","24","25"] 

那么为什么我在控制器上什么也没得到呢?这两天给我带来了麻烦,所以请帮忙!谢谢!!

更新 我已将我的 javascript 部分更新为我当前使用的内容。此部分现在将模型返回到带有 ReportingFilers 和 DealSummaries 对象的控制器,但其中的所有值都是空的。

这可能与作为字符串的值有关吗?如果是这样,我该如何解决这个问题?

【问题讨论】:

方法是什么样的?方法的输入参数是否命名为model? 你能把你的动作签名贴在这里吗? 你试过调试MVC吗? Microsoft 符号服务器上有源代码,因此您应该能够在 JSON 类(JsonModelBinding 或类似)中放置断点以查看发生了什么。您还应该确保您的 JSON 数据的发布内容类型也是正确的。 【参考方案1】:

将您的 $.getJSON 行更改为:

$.ajax( 
   url: '@Url.Action("FilterReports")',
   data: JSON.stringify(viewModel),
   contentType: 'application/json',
   dataType: 'json',
   success: function (data)  alert(data); 
);

这样 MVC 知道它正在接收 JSON 并将其正确绑定到您的模型。

【讨论】:

将此与@IAbstractDownvoteFactory 的答案结合起来,我更近了一步,现在我有了带有 ReportingFilters 和 DealSummary 对象的模型对象,但现在它们的所有属性都为空,即使我正在向它们传递值。 当你完全尝试我发布的内容时会发生什么? 我得到一个带有两个空对象的模型。 不幸的是,我只能接受一个作为我问题的答案,所以你明白了,因为你的帖子对解决我的问题最有帮助。从 $.getJSON 切换到 $.ajax 做出了最重要的贡献,因为其他人都以此为基础。谢谢大家! 哦,不会的。【参考方案2】:

您可以尝试以下几种不同的方法:

如果你想使用DefaultModelBinder:ASP.NET MVC3 JSON Model-binding with nested class,显然你不应该在你的对象中使用可为空的属性。因此,您可以尝试使您的 int 不可为空,或者如果这不是一个选项,请自己实现 IModelBinder

您是否使用SerializableAttribute 标记了您的课程?

尝试将 ajax 方法中的类型参数设置为 'POST' - 默认情况下将使用 'GET'..type: 'POST'

尝试将 ajax 方法中的 contentType 参数显式设置为此...contentType: 'application/json; charset=utf-8'

最后,您确定使用的是 MVC 3,而不是 MVC 2?我问是因为 MVC 3 将 JsonValueProviderFactory 融入了框架,而 MVC 2 没有,如果您使用 MVC 2,这可能会解释您遇到的问题......

【讨论】:

谢谢!将其更新为帖子并进行字符串化为我提供了控制器中模型中的所有数据,但现在没有达到我的回发...有什么建议吗? 嗯,您的回发未到达是什么意思?如果在 FilterReports Action 中设置断点并进行调试,它会停止吗?而且您的模型中不再有空值?你的意思是没有达到ajax回调吗?如果是这样,你从你的行动中得到什么回报?您是否也尝试在 ajax 方法上指定 'error' 参数? 我指的是 ajax 回发,但我能够弄清楚。我没有从我的 FilterReports 方法返回 JSON。【参考方案3】:

好的,替换:

 model: JSON.stringify(viewModel) 

 model: viewModel 

您正在将对象与 JSON 字符串混合,因此 jQuery 将 JSON.stringify 整个对象。这将对 viewModel 进行双重编码。

【讨论】:

这更接近工作,模型对象不再为空,但它下面的 ReportingFilters 和 DealSummaries 对象是。 你能用整数替换你的字符串吗? ["21","22","23","24","25"] 变为 [21,22,23,24,25] 是否应该删除 stringify 来实现这一点? 不,你是如何构建那个 javascript 对象的? 你说得对,它是字符串化的。我正在使用ListBoxFor(m = m.SelectedItemIds, Model.SelectedItems),这是调用 ajax 查询之前全选 hack 的原因。我将如何替换字符串值?【参考方案4】:

这是我的建议,在您的控制器中,操作方法应如下所示:

public JsonResult FilterAction(string model)

   var viewModel=new JavaScriptSerializer().Deserialize<DealSummaryComparisonViewModel>(model);

还要确保您的请求得到正确的操作,并查看 Firebug。

【讨论】:

【参考方案5】:

试试这个:

var filters = new Object();
filters.SelectedRtoId = $('#SelectedRtoId').val();
filters.SelectedPricingPointId =  $('#SelectedPricingPointId').val();
filters.SelectedLoadTypeId = $('#SelectedLoadTypeId').val();
filters.SelectedBlockId = $('#SelectedBlockId').val();
filters.SelectedRevisionStatusId = $('#SelectedRevisionStatusId').val();

var dealSummaries = new Object(); 
dealSummarties.SelectedItemIds = $('#SelectedItemIds').val();

var viewModel = new Object(); 
viewModel.ReportingFilters = filters;
viewModel.DealSummaries = dealSummaries;

$('#selected-items select option').attr("selected", "selected");
$.getJSON('@Url.Action("FilterReports")',  model: JSON.stringify(viewModel) , function (data) 
            alert(data);
); 

【讨论】:

我收到与以另一种方式初始化它们相同的结果。 是的,我已经尝试了它们的组合,似乎初始化并没有什么不同。

以上是关于MVC3 & JSON.stringify() ModelBinding 返回空模型的主要内容,如果未能解决你的问题,请参考以下文章

JSON.stringify API 返回 415 (.net & angular)

JS int 数组到 MVC3 控制器

JSON.stringify() <input> 值作为数字?

qs.stringify和JSON.stringify()

尝试使用复制(JSON.stringify(结果))

qs.stringify和JSON.stringify的使用和区别