为什么这个javascript对象不能转换为C#类对象?

时间:2014-03-03 18:06:55

标签: c# javascript jquery ajax asp.net-mvc-4

我正在开发一个小型测试床应用程序,您可以在该应用程序中为应用程序提供音符名称,符号和八度音,并且它会发出音符发出的频率。

我遇到了通过AJAX发送到服务器的JavaScript对象的问题。但是,它根本不会映射到操作上的类。

发件人代码是JavaScript的一部分:

$someContainer.on('click', '.raise-pitch', function (e) {
    e.preventDefault();

    var $line = $(this).parents('.item-line'),
        // Cache GUI elements for this line.  Not pertinent.

    var data = {
        'model': {
            'NoteName': $noteName.val(),
            'Sign': $noteSign.val(),
            'Octave': $noteOctave.val()
        },
        'steps': 1
    };
    var dataString = JSON.stringify(data);

    $.ajax({
        type: 'POST',
        url: '@Url.Action("AlterPitch", "Home")',
        data: dataString,
        async: true,
        dataType: 'json',
        success: function (result) {
            // Unimportant things.
        }
    });
});

data对象中,您可以看到我有两件事:modelsteps。这些步骤决定了我们改变音符的程度。我已经确认note namesignoctave的值正在将其转换为数据对象。 steps是预先确定的。

然而,data对象映射到C#端的ViewModel,如下所示:

public class NoteViewModel
{
    public enum NoteSign
    {
        Natural,
        Sharp,
        Flat
    }

    public string NoteName { get; set; }
    public NoteSign Sign { get; set; }
    public int Octave { get; set; }
    public float Frequency { get; set; }

    private static readonly Dictionary<string, float> FrequencyLookup = new Dictionary<string, float>
        {
            {"C", 16.35f},
            {"C#", 17.32f},
            {"D", 18.35f},
            {"D#", 19.45f},
            {"E", 20.60f},
            {"F", 21.83f},
            {"F#", 23.12f},
            {"G", 24.50f},
            {"G#", 25.96f},
            {"A", 27.50f},
            {"A#", 29.14f},
            {"B", 30.87f}
        };

    // Methods...not important for reasons below.
}

...它本身封装在一个独特的视图模型中:

public class AlterPitchViewModel
{
    public NoteViewModel model;
    public int steps;

    public NoteViewModel AlterPitch()
    {
        model.ChangeStep(steps);
        return model;
    }
}

......或者至少它应该。我在控制器方法中设置了一个断点:

[HttpPost]
public ActionResult AlterPitch(AlterPitchViewModel model)
{
    return Json(model.AlterPitch(), JsonRequestBehavior.AllowGet);
}

...但该模型为空,这导致NullReference例外。

模型没有序列化到在此上下文中发送的对象。显然我还在做错事。 问题是......什么?

2 个答案:

答案 0 :(得分:1)

您的HttpPost方法必须有一个唯一的参数,即ViewModel。我的建议:为每个帖子创建一个viewModel WebMethod

所以这里:

public class AlterPitchViewModel
{
    public NoteViewModel note { get; set; };
    public int Steps { get; set; };
}

并相应地调整您的Javascript。无需将您的javascript模型实例命名为ASP方法中的参数 - &gt;一个对象到达,只有一个参数可用,所以没有歧义。

答案 1 :(得分:1)

这种方法对我有用。

服务器端:

首先,创建ViewModel

public class TestViewModel
{
    public string Id { get; set; }
    public string Description { get; set; }
}

然后,在Controller中:

[HttpPost]
public ActionResult TestingViewModel(TestViewModel udata)
{
   // Stuff.
}

客户端:

function CallTestingViewModel() {

    // We create the javascript object based on the 
    // definition of our C# ViewModel class.
    var udata = {
        Id: 1,
        Description: 'This is a test.'
    };

    // Calling the C# method via AJAX.
    $.when(GenericAjaxCall('Home/TestingViewModel', false, udata)).then(function (result) {
        // do stuff
    });

}


// Return the AJAX call as a Promise Object
function GenericAjaxCall(controllerUrl, async, clientData) {
    return $.ajax({
        type: 'POST',
        async: async,
        url: controllerUrl,
        data: JSON.stringify(clientData),
        contentType: 'application/json;',
        dataType: 'json'
    });
}

希望它有所帮助。