1

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

然后,我还将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,并且不绑定数据。只有“标题”值是绑定的。

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() { 
    }); 

上面的代码是我如何提交数据到服务器。当我发布数据时,所有值都为空,并且mvc不是绑定数据。但是,当我绑定的值,而无需使用复杂的型像这样

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

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

+0

你不能将一个对象数组('textContents')绑定到'string'。但是,为什么不只是一个带有'string content'和'HttpPostedFileBase'的模型,然后主模型包含该模型的集合,以便内容和文件关联在一起? –

+0

你只能添加简单的'name/value'对来形成数据,而不是对象的集合。 –

+0

你的意思是数组的字符串和HttpPostedFileBase数组? –

回答

2

变化的模型,让你得到的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) 
+0

谢谢sooooo多。这就是我需要的。非常完美的答案。 –