如何使用 HttpWebRequest 将数据发布到 MVC 控制器?
Posted
技术标签:
【中文标题】如何使用 HttpWebRequest 将数据发布到 MVC 控制器?【英文标题】:How do I post data to MVC Controller using HttpWebRequest? 【发布时间】:2011-09-10 09:05:13 【问题描述】:我正在尝试将数据发布到 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();
当我将请求的内容类型设置为“application/x-www-form-urlencoded”时,GetReponse() 失败并显示服务器错误代码 500。当我将其注释掉并且仅对 xml 数据“interchangeXml”进行 httpencode 时, post 已发送,但只有第三个参数“label”到达控制器。其他为空。
当这些值之一是 xml 数据时,将值发布到控制器操作的正确方法是什么?
谢谢!
更新
我通过查询字符串发送除了 XML 之外的所有参数。但是,现在的问题是我不知道如何访问控制器操作中发布的数据。有人可以告诉我如何使用控制器操作从 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
);
【问题讨论】:
您的 MVC 操作期望的数据结构是什么?你能不能只在 xml 中发布所有数据,而不是查询字符串? 控制器操作需要 4 个字符串:interchangeXml、hwid、本地化和标签。不.. xml 不会也不会包含我尝试发布的其他值。 您是否尝试过使用 Fiddler 或 Firebug 之类的工具来准确查看您的客户端向服务器发送的内容?它可能无法正确输出。 我正在使用 c# 从 thik 客户端发出 httprequest。该请求不是来自浏览器,所以我认为 firebug 或 fiddler 不适用 我认为@Tridus 的意思是通过它的Web 界面访问该站点并摆弄请求以查看是否可以匹配它。即使您有四个不同的值,其中之一是 xml,您也可以使用 xml 来编写整个帖子,或者 json 和 MVC 应该足够聪明,可以将对象放在一起。我知道至少 MVC 3 会做到这一点。 【参考方案1】:包含所有这些请求和响应的客户端代码过于复杂且不安全。您没有对任何请求参数进行编码,更不用说这个 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
POST 值反序列化回Foo
实例。现在这是严肃的事情。
【讨论】:
感谢您提供完整的解决方案。我将尝试使用 WebClient 对象来简化事情。你说我没有对 xml 进行编码。字符串交换Xml = HttpUtility.UrlEncode(stringWriter.GetStringBuilder().ToString());这不是编码 xml 的正确方法吗? WebClient 只是收到 500 而不执行操作。既然动作需要一个视图模型,那么路由应该如何看待。我按照您的建议创建了一个 viewModel。 @Darin 我的 catch 块中的状态报告“协议错误”。 "远程服务器返回错误:(500) Internal Server Error" @Nick,看看内部异常。它应该是一个 HttpException,您可以从中提取来自服务器的确切响应消息。或者让您的服务器应用程序记录错误,以便您可以进一步缩小问题范围。恐怕从您提供的信息(应用程序抛出 500 状态码)中,我无法为您提供太多帮助。 @Darin 不幸的是,没有内部异常,并且异常并没有为我提供任何不那么模糊的东西。【参考方案2】:我在这里和同一个野兽搏斗:Trying to set up a controller action as Xml endpoint
您可能会收到内部服务器错误,因为您启用了页面验证(解决方案:使用 ValidateInput(false) 添加),或者您没有在请求中发送 Accept-Encoding 标头。我非常想听听如何让 MVC 在没有 Accept-Encoding HTTP 标头的情况下接受发布的输入...
【讨论】:
【参考方案3】:我刚刚发现您可以调用控制器,甚至是依赖注入的控制器,甚至可以从使用“T4MVC”Nuget 包的 Web 窗体代码后面调用:
https://github.com/T4MVC/T4MVC
【讨论】:
以上是关于如何使用 HttpWebRequest 将数据发布到 MVC 控制器?的主要内容,如果未能解决你的问题,请参考以下文章