【问题标题】:MVC model binding complex type that has a property of complex type collection with Angular JSMVC 模型绑定具有复杂类型集合属性的复杂类型与 Angular JS
【发布时间】:2017-03-26 10:40:19
【问题描述】:

我正在使用 Angular JS 和 ASP.NET MVC 开发一个 Web 应用程序。但是我遇到了模型绑定复杂类型的问题。我正在上传文件列表,基本上是字符串列表。在数据库中,它们(字符串列表和文件列表)是相同的列和表,因为我在文件上传后保存了路径。对于字符串,我使用文件路径保存同一列。例如,一个数据库表有 Id(int) 和 Data(string) 列。

然后我将 AngularJS 发布的字符串数据保存在数据列中,对于文件路径,也保存在数据列中。但重点是,我需要记住顺序。例如,用户添加一个文本字段然后输入值,然后动态添加文件字段然后选择文件,然后添加一个文本字段并再次输入值。所以顺序必须是 ["text 1 value" , File , "text 2 value" ]。但问题是我们无法将 HttpPostedFileBase 的文件和字符串的文本值混合的数据列表绑定。所以我所做的是创建如下视图模型。

    public class CreateBlogVM
    {
        [Required]
        [MaxLength(250)]
        public string Title { get; set; }
        [Required]
        public ContentModel[] TextContents { get; set; }
        [Required]
        public ContentFileModel[] Files { get; set; }
    }

    public class ContentModel
    {
        public int OrderNo { get; set; }
        public string Content { get; set; }
    }

    public class ContentFileModel
    {
        public int OrderNo { get; set; }
        public HttpPostedFileBase File { get; set; }
    }

正如您在上面看到的,CreateBlogVM 将是我现在绑定的 ViewModel。该类将具有两个复杂类型的属性——我在上面解释过的 TextContents 和 Files。所以为了记住顺序,我创建了一个带有 OrderNo 字段的复杂类型(客户端将传递这个值),正如你在上面看到的,因为我们无法绑定这样的数据列表

[HttpPostedFileBase, String, String, HttpPostedFileBase]

但问题是当我从 Angular js 发布数据时,所有值都是 null 并且没有绑定数据。只有“Title”值具有约束力。

    var textContents = new Array();
    var photoContents = new Array();

    for(var i=0; i<$scope.rows.length; i++)
    {
        if($scope.rows[i].type=="text")
        {
            var value = $scope.rows[i].value;
            if (value == "" || value == null) {
                showAlert("Text field should not be empty", "danger");
                return;
            }
            else {
                var content = { OrderNo: i, Content: value }
                textContents.push(content)
            }
        }
        else if($scope.rows[i].type=="photo")
        {
            var file = $scope.rows[i].file;
            if(file==null)
            {
                showAlert("Photo file is required", "danger");
                return;
            }
            else {
                var content = { OrderNo: i, File: file };
                photoContents.push(file);
            }
        }
    }

    var fd = new FormData();
    fd.append('Title', $scope.title);
    fd.append("TextContents", textContents);
    fd.append("Files", photoContents);

    $http.post("/Admin/Blog/Create", fd, {
        transformRequest: angular.identity,
        headers: { 'Content-Type': undefined }
    })

    .success(function () {
    })

    .error(function () {
    });

以上代码是我如何向服务器提交数据。当我发布数据时,所有值都是 null 并且 mvc 没有绑定数据。但是当我绑定值而不使用像这样的复杂类型时

public JsonResult Create(HttpPostedFileBase files, String contents, String title)

但是如果我像上面那样绑定,我不能对文件和字符串内容进行排序。那么我的代码有什么问题?如何绑定具有复杂类型对象属性列表的复杂数据?

【问题讨论】:

  • 您不能将对象数组 (textContents) 绑定到 string。但为什么不只是一个带有string contentHttpPostedFileBase 的模型,然后主模型包含该模型的集合,以便将内容和文件关联在一起?
  • 您只能添加简单的name/value 对来形成数据,而不是对象集合。
  • 你的意思是字符串数组和HttpPostedFileBase数组?
  • 如果我使用旧方法,我可以将字符串集合与表单数据绑定。
  • 对于 HttpPostedFileBase 数组和字符串数组是不行的,因为我需要将 OrderNo 与它们一起传递。

标签: angularjs asp.net-mvc model-binding angular-http complextype


【解决方案1】:

更改模型,以便在Content 和关联的File 之间获得直接关系(Order 属性是不必要的)

public class CreateBlogVM
{
    [Required]
    [MaxLength(250)]
    public string Title { get; set; }
    public List<FileVM> Files { get; set; }
}
public class FileVM
{
    [Required]
    public string Content { get; set; }
    [Required]
    public HttpPostedFileBase Image { get; set; }
}

您只能将简单的 name/value 对附加到 FormData(而不是对象数组)。在您的循环中,使用

追加数据
var fd = new FormData();
fd.append('Title', $scope.title);
for (var i=0; i<$scope.rows.length; i++)
{
    ....
    var content = $scope.rows[i].value;
    fd.append('Files[' + i + '].Content', content);
    ....
    var file = $scope.rows[i].file;
    fd.append('Files[' + i + '].Image', file);
}
....

以便您使用与您的集合属性相关的索引器生成名称(Files[0].ContentFiles[0].ImageFiles[1].Content 等)

那么你的 POST 方法签名将是

public JsonResult Create(CreateBlogVM model)

【讨论】:

  • 非常感谢。这就是我所需要的。非常完美的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多