如何通过一个复杂的视图模型为通过Ajax调用的控制器操作使用JSON在净MVC4?视图、控制器、模型、复杂

2023-09-10 19:27:14 作者:无作业一身轻

所以,我走遍堆栈溢出就像我可能可能,但没有找到一个答案,这个具体问题。道歉,如果这已经问。

So I scoured Stack Overflow as much as I possibly could and couldn't find an answer to this specific issue. Apologies if this has already been asked.

我找到了答案:

如何对象/类传递给一个动作 如何通过查询字符串的对象传递给一个动作 如何通过JSON对象传递给一个动作 如何将一个多态对象传递给一个动作,有一个自定义模型绑定过程中,它

假设你有以下code,你怎么能结合上述技术为一体的解决方案。所以我想打在控制器上有一个JSON对象的动作(使用jQuery AJAX调用),通过在一个视图模型的动作,并将其确定正确的多态类型(在这种情况下,通知的类型) - 可能通过使用自定义模型绑定

Suppose you have the following code, how can you combine the above techniques into one solution. So I'd like to hit the action on the controller (using the jquery ajax call) with a json object, pass in a view model to the action, and have it determine the the correct polymorphic type (in this case, type of Notification) - possibly by using a custom model binder.

请注意:这是用来说明问题的例子code

Note: this is example code used to illustrate the issue.

型号:

public class Notification
{
    public int ID { get; set; }
    public string ApplicationID { get; set; }
    public string Description { get; set; }
    public System.DateTime DateStamp { get; set; }
}

public class WarningNotification : Notification
{
    public string WarningText { get; set; }
}

public class AlertNotification : Notification
{
    public string AlertText { get; set; }
    public int AlertId { get; set; }
}

查看型号:

public class SaveNotificationViewModel
{
    public Notification Notification { get; set; }
    public string Hash { get; set; }
    public List<int> Users { get; set; }
}

控制器操作:

Controller action:

public ActionResult Save(SaveNotificationViewModel model)
{
    //code inside method irrelevant...
}

模型绑定:

public class NoticationModelBinder : DefaultModelBinder
{
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
    {
        var typeValue = bindingContext.ValueProvider.GetValue("ModelType");
        var type = Type.GetType((string)typeValue.ConvertTo(typeof(string)), true);

        if (!typeof(Notification).IsAssignableFrom(type))
        {
            throw new InvalidCastException("Bad type");
        }

        var model = Activator.CreateInstance(type);
        bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, type);
        return model;
    }
}

那派我来的主要是借这个兔子洞,然后code最初的问题来源: Methodology传递的组合:列表&LT;&gt;中对象和原语,一个ASP MVC控制器动作

Source of initial question that sent me down this rabbit hole and code largely borrowed from: Methodology for passing a mix of: list<>, object and primitives to an ASP MVC controller action

推荐答案

因此​​,这里就是我想出了...我包括code为一个WarningNotification和AlertNotification。

So here's what I came up with... I included code for both a WarningNotification and an AlertNotification.

这是我忽略了一个关键的对我来说是:

The key for me that I had overlooked were:

要坚持ModelType在JSON的根目录下,并没有下通知preFIX(如Notification.ModelType - 这是错误的...不这样做的)。 在各个领域的根目录下键入go(通知在这种情况下),所以对于特定类型的字段是仍然$ pfixed有p $通知。 - 见Notification.AlertId

Javascript的code,以配合它一起:

Javascript code to tie it all together:

// this is an example warning notification
var data =
    {
        "Notification.Id": '21',
        "Notification.ApplicationId": 'TARDIS',
        "Notification.Description": "The most important warning notification ever!",
        "Notification.WarningText": "I gave them the wrong warning. I should have told them to run, as fast as they can. Run and hide, because the monsters are coming - the human race.",
        "ModelType": 'Models.WarningNotification',
        "Hash": '27ad5218-963a-4df8-8c90-ee67c5ba9f30'
    };

// this is an example alert notification
var data =
    {
        "Notification.Id": '21',
        "Notification.ApplicationId": 'TARDIS',
        "Notification.Description": "The most important alert notification ever!",
        "Notification.AlertText": "Rose,before I go, I just want to tell you, you were fantastic. Absolutely fantastic. And you know what....so was I.",
        "Notification.AlertId": "1024",
        "ModelType": 'Models.AlertNotification',
        "Hash": '27ad5218-963a-4df8-8c90-ee67c5ba9f32'
    };

$.ajax({
    type: 'POST',
    url: '/notification/save',
    dataType: 'json',
    data: data,
    success: function (result) {
        console.log('SUCCESS:');
        console.log(result);
    },
    error: function (xhr, ajaxOptions, thrownError) {
        console.log('ERROR:');
        console.log(thrownError);
    }
});