如何使用HttpWebRequest将数据发布到MVC Controller?

我试图将数据发布到MVC控制器操作但到目前为止一直没有成功。

以下是post数据的结构:

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-form-urlencoded”时,GetReponse()失败并显示服务器错误代码500.当我将其注释掉并且仅对xml数据进行httpencode时,“interchangeXml”,发送post但只有第3个参数“label”到达控制器。 其他人都是空的。

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

谢谢!

更新

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

更新

我已经重构了上面的代码来使用Darin给我的建议。 我正在使用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 } ); 

客户端代码过于复杂且不安全,包含所有这些请求和响应。 您没有编码任何请求参数,更不用说这个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序列化器(或其他)将InterchangeDocument POSTed值反序列化为Foo实例。 现在这是一项严肃的事业。

我在这里摔跤同样的野兽: 尝试将控制器动作设置为Xml端点

您可能会收到内部服务器错误,因为您已启用页面validation(解决方案:带有ValidateInput(false)的addotate),或者您没有在请求中发送Accept-Encoding标头。 我非常想听听如何在没有Accept-Encoding HTTP标头的情况下让MVC接受发布的输入…

我刚刚发现你可以调用一个控制器,甚至是一个dependency injection的控制器,即使是使用“T4MVC”Nuget包后面的Web窗体代码:

https://github.com/T4MVC/T4MVC