Jquery 在.NETMVC4中,如何使用JSON通过ajax调用将复杂的视图模型传递到控制器操作?

Jquery 在.NETMVC4中,如何使用JSON通过ajax调用将复杂的视图模型传递到控制器操作?,jquery,ajax,json,asp.net-mvc-4,polymorphism,Jquery,Ajax,Json,Asp.net Mvc 4,Polymorphism,所以我尽可能多地搜索堆栈溢出,但找不到这个特定问题的答案。如果已经有人问过,我会道歉 我找到了以下问题的答案: 如何将对象/类传递给动作 如何通过查询字符串将对象传递给操作 如何通过json将对象传递给动作 如何将多态对象传递给动作并让自定义模型绑定器处理它 假设您有以下代码,如何将上述技术组合到一个解决方案中。因此,我希望使用json对象在控制器上执行操作(使用jquery ajax调用),将视图模型传递给操作,并让它确定正确的多态类型(在本例中为通知类型)——可能是通过使用自定义模型绑定

所以我尽可能多地搜索堆栈溢出,但找不到这个特定问题的答案。如果已经有人问过,我会道歉

我找到了以下问题的答案:

  • 如何将对象/类传递给动作
  • 如何通过查询字符串将对象传递给操作
  • 如何通过json将对象传递给动作
  • 如何将多态对象传递给动作并让自定义模型绑定器处理它
假设您有以下代码,如何将上述技术组合到一个解决方案中。因此,我希望使用json对象在控制器上执行操作(使用jquery ajax调用),将视图模型传递给操作,并让它确定正确的多态类型(在本例中为通知类型)——可能是通过使用自定义模型绑定器

注意:这是用于说明问题的示例代码

型号:

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; }
}
模型活页夹:

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;
    }
}
最初的问题的来源让我陷入了这个兔子洞,代码主要是从以下方面借来的:

因此,我希望使用json对象在控制器上执行操作(使用jquery ajax调用),将视图模型传递给操作,并让它确定正确的多态类型(在本例中为通知类型)——可能是通过使用自定义模型绑定器

我建议不要使用单一操作。首先,尽管很容易实现,但定制模型绑定与采用基类型或接口的操作相结合通常会变得更难调试、更难进行单元测试,任何查看控制器操作的人都无法仅通过查看操作本身来了解发生了什么

我强烈建议创建特定于请求的操作

我将它们简化为示例的相关代码

public ProcessNotify(Notification model)
{
  this.SharedNotifyCode(model);

  // specific Notification only code
}

public ProcessWarningNotification(WarningNotification model)
{
  this.SharedNotifyCode(model);

  // specific WarningNotification only code
}

public ProcessAlertNotification(AlertNotification model)
{
  this.SharedNotifyCode(model);

  // specific AlertNotification only code
}

private SharedNotifyCode(Notification notification)
{
  // shared code
}
这很容易维护、调试和测试,代码本身也是自文档化的

javascript(jQuery)代码也可以做同样的事情:


这就是我想到的。。。我包括了警告通知和警报通知的代码

我忽略的关键是:

  • 将“ModelType”粘贴在JSON的根级别,而不是通知前缀下面(如“notification.ModelType”-这是错误的…不要这样做)
  • 所有字段都在根类型下(在本例中为通知),因此专用类型的字段仍以“通知”作为前缀-请参阅“Notification.AlertId”
  • Javascript代码将所有内容绑定在一起:

    // 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);
        }
    });
    

    您还没有提供CreateViewModel的详细信息,应该包括在内。@ErikPhilips-谢谢!那是一份复制品/面食。。。看我上面的编辑。这是不是贴了两次?可能会考虑删除第二个答案。@埃里克飞利浦-谢谢你花时间张贴这个。虽然这是一个有效的选择,但它并不能完全回答我提出的问题。不过,我会考虑这个方法。这个答案的帮助人是@Darin Dimitrov!参考资料:及
    function ProcessNotify()
    {
      notify = {
        ID = 1,
        ApplicationID = 2,
        Description = "description",
        DateStamp = new Date() // something like this.. forgot JS datetimes
        };
    
      SendNotify(notify, "ProcessNotify");
    }
    
    function ProcessWarning()
    {
      notify = {
        ID = 1,
        ApplicationID = 2,
        Description = "description",
        DateStamp = new Date(), // something like this.. forgot JS datetimes
        WarningText = "Oh noes!"
        };
    
      SendNotify(notify, "ProcessWarningNotification");
    }
    
    function ProcessAlert()
    {
      notify = {
        ID = 1,
        ApplicationID = 2,
        Description = "description",
        DateStamp = new Date(), // something like this.. forgot JS datetimes
        AlertText = "Oh noes!",
        AlertId = 3
        };
    
      SendNotify(notify, "ProcessAlertNotification");
    }
    
    function SendNotify(notify, action)
    {
      var jqXHR = $.ajax({
        url: '/' + Controller + '/' + action,
        data: notify,
        type: "POST",
        success: function(result)
        {
        }
        // etc
      });
    }
    
    // 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);
        }
    });