【问题标题】:Why doing POST throws an exception in MVC 4?为什么在 MVC 4 中做 POST 会引发异常?
【发布时间】:2012-08-11 13:45:27
【问题描述】:

我正在尝试做这样的 POST:

    HttpClient hc = new HttpClient();
    byte[] bytes = ReadFile(@"my_path");

    var postData = new List<KeyValuePair<string, string>>();
    postData.Add(new KeyValuePair<string, string>("FileName", "001.jpeg"));
    postData.Add(new KeyValuePair<string, string>("ConvertToExtension", ".pdf"));
    postData.Add(new KeyValuePair<string, string>("Content", Convert.ToBase64String(bytes)));

    HttpContent content = new FormUrlEncodedContent(postData);
    hc.PostAsync("url", content).ContinueWith((postTask) => {
    postTask.Result.EnsureSuccessStatusCode();
    });

但我收到此异常:

无效的 URI:Uri 字符串太长。

抱怨这条线:HttpContent content = new FormUrlEncodedContent(postData);。对于小文件,它可以工作,但我不明白为什么对于较大的文件它不起作用?

当我发布 POST 时,content 可能会更大...那为什么它会抱怨 URI?

【问题讨论】:

    标签: asp.net-mvc asp.net-web-api


    【解决方案1】:

    您应该使用 MultipartFormDataContent (http://msdn.microsoft.com/en-us/library/system.net.http.multipartformdatacontent%28v=vs.110%29) 而不是 FormUrlEncodedContent,它将您的数据作为“application/x-www-form-urlencoded”发送。

    因此,即使您使用 POST 动词,它仍然会发布到包含您的数据的很长的 url,因此会出现错误。

    内容类型“application/x-www-form-urlencoded”效率低下 用于发送大量二进制数据或包含 非 ASCII 字符。内容类型“multipart/form-data”应该是 用于提交包含文件、非 ASCII 数据和 二进制数据。

    见:http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1

    对于示例,请查看此答案:ASP.NET WebApi: how to perform a multipart post with file upload using WebApi HttpClient

    【讨论】:

    • 谢谢!你有任何例子如何做到这一点?它是否正确? MultipartFormDataContent multipartFormDataContent = new MultipartFormDataContent(); multipartFormDataContent.Add(new FormUrlEncodedContent(postData));
    • @CristianBoariu 更新了我的答案以链接示例
    • @mathieu 该示例仍然抛出异常,因为 FormUrlEncodedContent 是构建的
    【解决方案2】:

    我知道这已经得到解答,但我遇到了同样的问题,发现这是 FormUrlEncodedContent 类中的一个限制。错误的原因是对象的编码正在由Uri.EscapeDataString() 处理。 This post explains it on CodePlex. 我最终使用 HTTPUtility 类提出了自己的 Url Encode 解决方案。

    using System.Collections.Generic;
    using System.Linq;
    using System.Net.Http;
    using System.Text;
    using System.Web;
    
    namespace Wfm.Net.Http
    {
        public class UrlContent : ByteArrayContent
        {
            public UrlContent(IEnumerable<KeyValuePair<string, string>> content)
                : base(GetCollectionBytes(content, Encoding.UTF8))
            {
            }
    
            public UrlContent(byte[] content, int offset, int count) : base(content, offset, count)
            {
            }
    
            private static byte[] GetCollectionBytes(IEnumerable<KeyValuePair<string, string>> c, Encoding encoding)
            {
                string str = string.Join("&", c.Select(i => string.Concat(HttpUtility.UrlEncode(i.Key), '=', HttpUtility.UrlEncode(i.Value))).ToArray());
                return encoding.GetBytes(str);
            }
        }
    
    
    }
    

    我写了一个小article 我是如何实现它的。希望这对遇到同样问题的人有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多