如何使用HttpWebRequest将数据发布到MVC控制器?

问题描述:

我想发布数据到MVC控制器的行动,但到目前为止一直没有成功。如何使用HttpWebRequest将数据发布到MVC控制器?

这里是后的数据的结构:

private string makeHttpPostString(XmlDocument interchangeFile) 
    { 
     string postDataString = "uid={0}&localization={1}&label={2}&interchangeDocument={3}"; 

     InterchangeDocument interchangeDocument = new InterchangeDocument(interchangeFile); 
     using (var stringWriter = new StringWriter()) 
     using (var xmlTextWriter = XmlWriter.Create(stringWriter)) 
     { 
      interchangeFile.WriteTo(xmlTextWriter); 
      string interchangeXml = HttpUtility.UrlEncode(stringWriter.GetStringBuilder().ToString()); 
      string hwid = interchangeDocument.DocumentKey.Hwid; 
      string localization = interchangeDocument.DocumentKey.Localization.ToString(); 
      string label = ConfigurationManager.AppSettings["PreviewLabel"]; 

      return (string.Format(postDataString, hwid, localization, label, interchangeXml)); 
     } 

    } 

这里是请求:

HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create(controllerUrl); 

     webRequest.Method = "POST"; 
     // webRequest.ContentType = "application/x-www-form-urlencoded"; 

     string postData = makeHttpPostString(interchangeFile); 
     byte[] byteArray = Encoding.UTF8.GetBytes(postData); 
     webRequest.ContentLength = byteArray.Length; 

     using (Stream dataStream = webRequest.GetRequestStream()) 
     { 
      dataStream.Write(byteArray, 0, byteArray.Length); 
     } 

     HttpWebResponse webresponse = (HttpWebResponse) webRequest.GetResponse(); 

当我设置请求的contentType中为“application/X WWW的形状配合urlencoded“GetReponse()失败,服务器错误代码为500.当我注释掉并且只有xpen数据为”interchangeXml“时,才会发送该帖子,但只有第三个参数”label“到达控制器。其他人为空。

当这些值之一是xml数据时,将值发布到控制器操作的正确方法是什么?

谢谢!

更新

我把所有的参数通过查询字符串中的XML除外。但是,现在的问题是我不知道如何访问控制器操作中发布的数据。有人能告诉我如何从我的Controller Action中通过HttpRequest访问xml吗?

更新

我已经重构上面的代码由达林使用建议做给我。我正在使用WebClient UploadValues()接收内部服务器错误(500)。

操作:

[AcceptVerbs(HttpVerbs.Post)] 
     public ActionResult BuildPreview(PreviewViewModel model) 
     { 
      ... 
     } 

请求:

private string PostToSxController(XmlDocument interchangeFile, string controllerUrl) 
     { 
      var xmlInterchange = new InterchangeDocument(interchangeFile); 
      using (var client = new WebClient()) 
      { 
       var values = new NameValueCollection() 
           { 
            {"uid", xmlInterchange.DocumentKey.Hwid}, 
            {"localization", xmlInterchange.DocumentKey.Localization.ToString()}, 
            {"label", ConfigurationManager.AppSettings["PreviewLabel"]}, 
            {"interchangeDocument", interchangeFile.OuterXml } 
           }; 

       byte[] result = null; 

       try 
       { 
        result = client.UploadValues(controllerUrl, values); 
       } 
       catch(WebException ex) 
       { 
        var errorResponse = ex.Response; 
        var errorMessage = ex.Message; 
       } 

       Encoding encoding = Encoding.UTF8; 
       return encoding.GetString(result); 


      } 
     } 

路线:

routes.MapRoute(
       "BuildPreview", 
       "SymptomTopics/BuildPreview/{model}", 
       new { controller = "SymptomTopics", action = "BuildPreview", model = UrlParameter.Optional } 
      ); 
+0

什么是数据结构中的MVC的行动期待?难道你不只是发布所有的数据在XML中,而不是查询字符串? – Jay 2011-06-07 20:24:26

+0

控制器操作期望4个字符串:interchangeXml,hwid,本地化和标签。否。xml不会包含我尝试发布的其他值。 – Nick 2011-06-07 20:37:47

+0

您是否尝试过使用像Fiddler或Firebug这样的工具来查看您的客户端正在发送给服务器的内容?它可能无法正确显示。 – Tridus 2011-06-07 20:39:04

与所有这些请求和响应过于复杂和不安全的客户端代码。你没有编码任何你的请求参数,更不用说这个XML,如果你没有正确编码它可能会破坏一切。

为此,我将简化和留言编码等的管道代码...到.NET框架:

using (var client = new WebClient()) 
{ 
    var values = new NameValueCollection 
    { 
     { "uid", hwid }, 
     { "localization", localization }, 
     { "label", label }, 
     { "interchangeDocument", interchangeFile.OuterXml }, 
    }; 
    var result = client.UploadValues(controllerUrl, values); 
    // TODO: do something with the results returned by the controller action 
} 

至于服务器端来讲,因为每个正确设计ASP。NET MVC应用程序,它显然会使用一个视图模型:

public class MyViewModel 
{ 
    public string Uid { get; set; } 
    public string Localization { get; set; } 
    public string Label { get; set; } 
    public string InterchangeDocument { get; set; } 
} 

有:

[HttpPost] 
public ActionResult Foo(MyViewModel model) 
{ 
    // TODO: do something with the values here 
    ... 
} 

显然,这可以通过编写反映你的XML文档的结构视图模型进一步采取的一个步骤:

public class Foo 
{ 
    public string Bar { get; set; } 
    public string Baz { get; set; } 
} 

,然后您的视图模式将成为:

public class MyViewModel 
{ 
    public string Uid { get; set; } 
    public string Localization { get; set; } 
    public string Label { get; set; } 
    public Foo InterchangeDocument { get; set; } 
} 

,最后一部分是为Foo类型编写一个定制模型绑定器,该类型将使用XML串行器(或其他)将POST后的值反序列化回实例。现在这是严重的事情。

+0

谢谢你的解决方案。我将尝试使用WebClient对象来简化事情。你说我没有编码xml .. string interchangeXml = HttpUtility.UrlEncode(stringWriter.GetStringBuilder()。ToString());这不是编码xml的正确方法吗? – Nick 2011-06-07 22:48:47

+1

WebClient只收到一个500而没有触发该操作。该路线现在应该如何看待该操作期待viewModel。我创建了一个viewModel,就像你建议的那样。 – Nick 2011-06-08 00:17:14

+0

@尼克,这500错误的消息是什么? – 2011-06-08 06:23:33

我摔跤同样的野兽在这里:Trying to set up a controller action as Xml endpoint

你可能会得到内部服务器错误,因为无论你对页面验证(溶液:用addotate ValidateInput(假)),或者你不根据您的请求发送Accept-Encoding标头。我非常想听听我如何让MVC接受没有Accept-Encoding HTTP头的发布输入...

我刚刚发现,即使是从Web,我也可以调用一个控制器,甚至是一个依赖注入一个依赖项背后使用“T4MVC” NuGet包的形式代码:

https://github.com/T4MVC/T4MVC