我正在尝试将数据发布到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-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 }
);
答案 0 :(得分:12)
您的客户端代码过于复杂且不安全,包含所有这些请求和响应。您没有编码任何请求参数,更不用说这个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值反序列化为{{1}实例。现在这是一项严肃的事业。
答案 1 :(得分:1)
我在这里摔跤同样的野兽:Trying to set up a controller action as Xml endpoint
您可能收到内部服务器错误,因为您已启用页面验证(解决方案:带有ValidateInput(false)的addotate),或者您没有在请求中发送Accept-Encoding标头。我非常想听听如何在没有Accept-Encoding HTTP标头的情况下让MVC接受发布的输入......
答案 2 :(得分:0)
我刚刚发现你可以调用一个控制器,甚至是一个依赖注入的控制器,即使是使用“T4MVC”Nuget包后面的Web窗体代码: