Knockoutjs:将复杂类型发布到MVC控制器查询

时间:2014-01-01 18:43:06

标签: c# asp.net-mvc knockout.js

我一直在与这场斗争3天。     基本上,我有一个javascript对象发布到MVC控制器。在检查Request.Form.AllKeys namevalueCollection中的属性键名称时,我注意到我的子属性被[]包围,而MVC模型绑定器没有绑定这些值。

The values coming through on the controller look like this:

[6]: "Metadata[ScreenResolution]"
[7]: "Metadata[AudioCodec]"
[8]: "Metadata[VideoCodec]"
[9]: "Metadata[Format]"

My question is why is this happening. 
Edit: The "first-level properties are binding successfully, In the javascript, when the javascript object is being created, all the properties are being set correctly from KO"

MVC Model:

public class Movie
    {
        public int Id { get; set; }

        [Required]
        public string Name { get; set; }

        public string Directors { get; set; }

        public string Description { get; set; }

        public int GenreId { get; set; }

        public int YearId { get; set; }

        public MovieMetadata Metadata { get; set; }

        public int RatingId { get; set; }

        public string MovieUrl { get; set; }        

        public string Stars { get; set; }

        public string Duration { get; set; }       
    }

 public class MovieMetadata
    {

        public int Id { get; set; }

        public string ScreenResolution { get; set; }

        public string VideoCodec { get; set; }

        public string AudioCodec { get; set; }

        public int FormatId { get; set; }
    }

Knockout Js file:

var SimpleModelLoading = function (data) { //data: this is JSON result coming back form the action method
    var self = this;
    self.MovieModel = {};

    self.MovieName = ko.observable(data.Name);
    self.Description = ko.observable(data.Description);
    self.Directors = ko.observable(data.Directors);
    self.MovieUrl = ko.observable(data.MovieUrl);
    self.Stars = ko.observable(data.Stars);
    self.Duration = ko.observable(data.Duration);

    self.ScreenResolution = ko.observable(data.Metadata.ScreenResolution);
    self.AudioCodec = ko.observable(data.Metadata.AudioCodec);
    self.VideoCodec = ko.observable(data.Metadata.VideoCodec);    

    self.selectedGenre = ko.observable();
    self.selectedYear = ko.observable();
    self.selectedRating = ko.observable();
    self.selectedFormat = ko.observable();

    self.MovieModel = ko.computed(function () {
        var movieModel =
        {
            Name: self.MovieName(),
            Description: self.Description(),
            GenreId: self.selectedGenre() == undefined ? undefined : self.selectedGenre().Key,
            YearId: self.selectedYear() == undefined ? undefined : self.selectedYear().Key,
            RatingId: self.selectedRating() == undefined ? undefined : self.selectedRating().Key,
            Directors: self.Directors(),
            Stars: self.Stars(),
            MovieUrl: self.MovieUrl(),
            Duration: self.Duration(),    
        };

        movieModel.Metadata =
        {
            ScreenResolution: self.ScreenResolution(),
            AudioCodec: self.AudioCodec(),
            VideoCodec: self.VideoCodec(),
            Format: self.selectedFormat() == undefined ? undefined : self.selectedFormat().Key
        };

        return movieModel;
    }, self);

    self.Genres = data.LookupData.Genre;
    self.Year = data.LookupData.Year;
    self.Rating = data.LookupData.Rating;
    self.Format = data.LookupData.Format;

    self.saveMovie = function () {
        var url = "/Movie/SaveMovie";

        $.ajax(
            {
                url: url,
                data: self.MovieModel(),
                type: "POST",
                success: function () {
                    alert('save successful');
                },
                error: function (xhr) {
                    alert(xhr.responseText);
                }
            });
    };
};

Movie View:

<div>
    <form method="POST">
        <div data-role="collapsible" data-collapsed="false" id="movieInfoContainer">
            <h2>Add New Video</h2>
            @* <div data-role="collapsible" data-collapsed="false">
                <h3>Movie Details</h3>
                   <div id="movieInfo">
                @Html.Partial("MovieDetails")
            </div>
            </div>*@

            <div data-role="collapsible" data-collapsed="true" id="movieMetadataContainer">
                <h3>Technical Specifications</h3>
                <div id="movieMetadata">
                    @Html.Partial("MovieMetadataDetails")
                </div>
            </div>
        </div>

        <p>
            <button data-bind="click: saveMovie">Save</button>
        </p>
    </form>
</div>

Movie Metadata View:

<p>
    Audio Encoding:<input data-bind="value: AudioCodec" />
</p>
<p>
    Video Encoding:<input data-bind="value: VideoCodec" />
</p>

<p>
    Screen Resolution:<input data-bind="value: ScreenResolution" />
</p>

<div class="clearSpaceLine"><span>Format:</span></div>
<select data-bind="options: Format, value: selectedFormat, optionsText: 'Value'"></select>
<br />

1 个答案:

答案 0 :(得分:5)

您正在直接发布可观察对象,但嵌套在其中的可观察对象是函数,而不是数据。

尝试替换此

data: self.MovieModel(),

用这个

data: ko.toJSON(self.MovieModel()),

有关此here

的更多信息