简体   繁体   English

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

[英]How do I post data to MVC Controller using HttpWebRequest?

I am trying to post data to MVC controller action but have been unsuccessful so far.我正在尝试将数据发布到 MVC controller 操作,但到目前为止还没有成功。

Here is the structure of the post data:这是帖子数据的结构:

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));
        }

    }

Here is the request:这是请求:

 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();

When I set the contenttype of the request to "application/x-www-form-urlencoded" GetReponse() fails with server error code 500. When I comment that out and only httpencode the xml data, "interchangeXml", the post is sent but only the 3rd parameter, "label" reaches the controller.当我将请求的内容类型设置为“application/x-www-form-urlencoded”时,GetReponse() 失败,服务器错误代码为 500。当我将其注释掉并且仅对 xml 数据“interchangeXml”进行 httpencode 时,将发送帖子但只有第三个参数“标签”到达 controller。 The others are null.其他的是 null。

What is the correct way to post values to a controller action when one of those values is xml data?当这些值之一是 xml 数据时,将值发布到 controller 操作的正确方法是什么?

Thanks!谢谢!

Update更新

I am send all the parameter with the exception of the XML via the query string.我通过查询字符串发送除 XML 之外的所有参数。 However, the problem now is that I do not know how to access the posted data in the controller action.但是,现在的问题是我不知道如何访问 controller 操作中发布的数据。 Can someone tell me how I access the xml from the HttpRequest from with my Controller Action?有人可以告诉我如何使用 Controller 操作从 HttpRequest 访问 xml 吗?

Update更新

I have refactored the above code to use the suggests made to me by Darin.我已经重构了上面的代码以使用 Darin 给我的建议。 I am recieveing an internal server error (500) using the WebClient UploadValues().我使用 WebClient UploadValues() 收到内部服务器错误 (500)。

Action:行动:

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

Request:要求:

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);


            }
        }

Route:路线:

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

Too complicated and unsafe your client code with all those requests and responses.对于所有这些请求和响应,您的客户端代码过于复杂和不安全。 You are not encoding any of your request parameters, not to mention this XML which is probably gonna break everything if you don't encode it properly.您没有对任何请求参数进行编码,更不用说这个 XML 如果您没有正确编码它可能会破坏一切。

For this reason I would simplify and leave the plumbing code about encoding, etc... to the .NET framework:出于这个原因,我将简化有关编码等的管道代码并将其留给 .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
}

As far as the server side is concerned, as every properly architected ASP.NET MVC application, it would obviously use a view model:就服务器端而言,作为每个正确架构的 ASP.NET MVC 应用程序,它显然会使用视图 model:

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

with:和:

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

Obviously this could be taken a step further by writing a view model reflecting the structure of your XML document:显然,这可以通过编写反映 XML 文档结构的视图 model 来更进一步:

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

and then your view model will become:然后您的视图 model 将变为:

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

and the last part would be to write a custom model binder for the Foo type that will use a XML serializer (or whatever) to deserialize back the InterchangeDocument POSTed value into a Foo instance.最后一部分是为Foo类型编写自定义 model 绑定程序,该绑定程序将使用 XML 序列化程序(或其他)将InterchangeDocument POSTed 值反序列化回Foo实例。 Now that's serious business.现在这是严肃的事情。

I'm wrestling the same beast over here: Trying to set up a controller action as Xml endpoint我在这里与同一头野兽搏斗: 尝试将 controller 操作设置为 Xml 端点

You may be getting the internal server error because either you have page validation on (solution: addotate with ValidateInput(false)), or you're not sending an Accept-Encoding header with your request.您可能会收到内部服务器错误,因为您有页面验证(解决方案:使用 ValidateInput(false) 添加),或者您没有在请求中发送 Accept-Encoding header。 I would very much like to hear how I can get MVC to accept posted input without the Accept-Encoding HTTP header...我非常想听听如何让 MVC 在没有接受编码 HTTP header 的情况下接受发布的输入...

I just found that you can call a controller, even a dependency injected one, even from a Web Forms code behind using the "T4MVC" Nuget package: I just found that you can call a controller, even a dependency injected one, even from a Web Forms code behind using the "T4MVC" Nuget package:

https://github.com/T4MVC/T4MVC https://github.com/T4MVC/T4MVC

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM