【问题标题】:ASP.NET MVC. How to create Action method that accepts and multipart/form-dataASP.NET MVC。如何创建接受和 multipart/form-data 的 Action 方法
【发布时间】:2011-07-18 11:55:16
【问题描述】:

我有一个控制器方法需要接受客户端作为 POST 请求发送的multipart/form-data。表单数据有 2 个部分。一个是序列化为application/json 的对象,另一部分是作为application/octet-stream 发送的照片文件。我的控制器上有这样的方法:

[AcceptVerbs(HttpVerbs.Post)]
void ActionResult Photos(PostItem post)
{
}

我可以在这里通过Request.File 毫无问题地获取文件。但是 PostItem 为空。 不知道为什么?任何想法

控制器代码:

/// <summary>
/// FeedsController
/// </summary>
public class FeedsController : FeedsBaseController
{
    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Photos(FeedItem feedItem)
    {
        //Here the feedItem is always null. However Request.Files[0] gives me the file I need  
        var processor = new ActivityFeedsProcessor();
        processor.ProcessFeed(feedItem, Request.Files[0]);

        SetResponseCode(System.Net.HttpStatusCode.OK);
        return new EmptyResult();
    }

}

网络上的客户端请求如下所示:

{User Agent stuff}
Content-Type: multipart/form-data; boundary=8cdb3c15d07d36a

--8cdb3c15d07d36a
Content-Disposition: form-data; name="feedItem"
Content-Type: text/xml

{"UserId":1234567,"GroupId":123456,"PostType":"photos",
    "PublishTo":"store","CreatedTime":"2011-03-19 03:22:39Z"}

--8cdb3c15d07d36a
Content-Disposition: file; filename="testFile.txt"
ContentType: application/octet-stream

{bytes here. Removed for brevity}
--8cdb3c15d07d36a--

【问题讨论】:

  • 您能在您的视图中发布解码代码吗?你在使用 ASP.NET MVC 1 吗?
  • 贴出了上面的代码。我正在使用 MVC3

标签: asp.net-mvc multipartform-data


【解决方案1】:

FeedItem 类是什么样的?对于我在帖子信息中看到的内容,它应该类似于:

public class FeedItem
{
    public int UserId { get; set; }
    public int GroupId { get; set; }
    public string PublishTo { get; set; }
    public string PostType { get; set; }
    public DateTime CreatedTime { get; set; }
}

否则不会绑定。您可以尝试更改操作签名,看看是否可行:

[HttpPost] //AcceptVerbs(HttpVerbs.Post) is a thing of "the olden days"
public ActionResult Photos(int UserId, int GroupId, string PublishTo
    string PostType, DateTime CreatedTime)
{
    // do some work here
}

您甚至可以尝试在您的操作中添加HttpPostedFileBase 参数:

[HttpPost]
public ActionResult Photos(int UserId, int GroupId, string PublishTo
    string PostType, DateTime CreatedTime, HttpPostedFileBase file)
{
    // the last param eliminates the need for Request.Files[0]
    var processor = new ActivityFeedsProcessor();
    processor.ProcessFeed(feedItem, file);

}

如果你真的觉得狂野和顽皮,请将HttpPostedFileBase 添加到FeedItem

public class FeedItem
{
    public int UserId { get; set; }
    public int GroupId { get; set; }
    public string PublishTo { get; set; }
    public string PostType { get; set; }
    public DateTime CreatedTime { get; set; }
    public HttpPostedFileBase File { get; set; }
}

最后一个代码 sn-p 可能是您最终想要的,但逐步分解可能会帮助您。

这个答案也可以帮助你朝着正确的方向前进:ASP.NET MVC passing Model *together* with files back to controller

【讨论】:

    【解决方案2】:

    正如@Sergi 所说,将 HttpPostedFileBase 文件参数添加到您的操作中,我不知道 MVC3 但对于 1 和 2,您必须在表单/视图中指定您将像这样发布多部分/表单数据:

    <% using (Html.BeginForm(MVC.Investigation.Step1(), FormMethod.Post, new { enctype = "multipart/form-data", id = "step1form" }))
    

    这是在我的控制器中:

    [HttpPost]
        [ValidateAntiForgeryToken]
        [Authorize(Roles = "Admin, Member, Delegate")]
        public virtual ActionResult Step1(InvestigationStep1Model model, HttpPostedFileBase renterAuthorisationFile)
        {
            if (_requesterUser == null) return RedirectToAction(MVC.Session.Logout());
    
            if (renterAuthorisationFile != null)
            {
                var maxLength = int.Parse(_configHelper.GetValue("maxRenterAuthorisationFileSize"));
                if (renterAuthorisationFile.ContentLength == 0)
                {
                    ModelState.AddModelError("RenterAuthorisationFile", Resources.AttachAuthorizationInvalid);
                }
                else if (renterAuthorisationFile.ContentLength > maxLength * 1024 * 1204)
                {
                    ModelState.AddModelError("RenterAuthorisationFile", string.Format(Resources.AttachAuthorizationTooBig, maxLength));
                }
            } 
            if(ModelState.IsValid)
            {
                if (renterAuthorisationFile != null && renterAuthorisationFile.ContentLength > 0)
                {
                    var folder = _configHelper.GetValue("AuthorizationPath");
                    var path = Server.MapPath("~/" + folder);
                    model.RenterAuthorisationFile = renterAuthorisationFile.FileName;
                    renterAuthorisationFile.SaveAs(Path.Combine(path, renterAuthorisationFile.FileName));
                }
                ...
                return RedirectToAction(MVC.Investigation.Step2());
            }
            return View(model);
        }
    

    希望对你有帮助!

    【讨论】:

      猜你喜欢
      • 2011-04-22
      • 2020-01-08
      • 1970-01-01
      • 2010-10-09
      • 1970-01-01
      • 1970-01-01
      • 2019-02-26
      • 2012-08-06
      • 2021-11-09
      相关资源
      最近更新 更多