如何将ViewModel序列化为XML并将其发送到远程服务器?

时间:2017-12-12 16:13:07

标签: c# xml asp.net-mvc http serialization

我有一个ASP.NET MVC 5应用程序,我在其中尝试序列化我的ViewModel并将其发送到远程第三方服务器进行数据处理。我不确定我做错了什么,但下面是我尝试过的代码。

首先,这是我的控制器中的POST方法,我试图序列化ViewModel并将其发送到远程服务器:

[HttpPost]
        public ActionResult Index(Transmission t)
        {
            ViewBag.ErrorMessage = "";
            ViewBag.OtherMessage = "";

            try
            {
                //serialize the ViewModel
                XmlResult xrs = new XmlResult(t);
                XDocument xdoc = XDocument.Parse(xrs.ToString());
                Stream stream = new MemoryStream(); //the memory stream to be used to save the xdoc
                XmlActionResult xar = new XmlActionResult(xdoc);
                xdoc.Save(stream);
                //xrs.ExecuteResult(ControllerContext);

                //POST the data to the external URL
                var url = "theUrl";
                var PostData = xar;


                var Req = (HttpWebRequest)WebRequest.Create(url);
                Req.ContentType = "application/xml";
                Req.Method = "POST";
                Req.Timeout = 60000;
                Req.KeepAlive = false;


                //build the string to send
                StringBuilder sb = new StringBuilder();

                using(StreamReader sr = new StreamReader(stream))
                {
                    string line; 
                    while((line = sr.ReadLine()) != null)
                    {
                        sb.AppendLine(line);
                    }
                    byte[] postBytes = Encoding.ASCII.GetBytes(sb.ToString());
                    Req.ContentLength = postBytes.Length;


                    using (Stream requestStream = Req.GetRequestStream())
                    {
                        requestStream.Write(postBytes, 0, postBytes.Length);
                        requestStream.Close();
                    }

                   using (var response = (HttpWebResponse)Req.GetResponse())
                    {
                        ViewBag.OtherMessage = response.ToString();
                        return View("Error"); //TODO: change this to success when I get the 500 error fixed
                    }
                }

            }
            catch (Exception ex)
            {
                string message = ex.Message;
                ViewBag.ErrorMessage = ex.Message;
                return View("Error");
            }
        }
    }

如上所示,我正在使用两个类,分别称为XmlActionResultXmlResultXmlResult类用于序列化ViewModel。以下是XmlResult类的实现:

public class XmlResult : ActionResult
    {
        private object objectToSerialize;

        /// <summary>
        /// Initializes a new instance of the <see cref="XmlResult"/> class.
        /// </summary>
        /// <param name="objectToSerialize">The object to serialize to XML.</param>
        public XmlResult(object objectToSerialize)
        {
            this.objectToSerialize = objectToSerialize;
        }

        /// <summary>
        /// Gets the object to be serialized to XML.
        /// </summary>
        public object ObjectToSerialize
        {
            get { return objectToSerialize; }
        }

        /// <summary>
        /// Serializes the object that was passed into the constructor to XML and writes the corresponding XML to the result stream.
        /// </summary>
        /// <param name="context">The controller context for the current request.</param>
        public override void ExecuteResult(ControllerContext context)
        {
            if (objectToSerialize != null)
            {
                context.HttpContext.Response.Clear();
                var xs = new System.Xml.Serialization.XmlSerializer(objectToSerialize.GetType());
                context.HttpContext.Response.ContentType = "xml";
                xs.Serialize(context.HttpContext.Response.Output, objectToSerialize);
            }
        }
    }

XmlResult类序列化ViewModel之后,我尝试使用XDocument类创建XmlActionResult。以下是XmlActionResult类的实现:

public sealed class XmlActionResult : ActionResult
    {
        private readonly XDocument _document;

        public Formatting Formatting { get; set; }
        public string MimeType { get; set; }

        public XmlActionResult(XDocument document)
        {
            if (document == null)
                throw new ArgumentNullException("document");

            _document = document;

            // Default values
            MimeType = "text/xml";
            Formatting = Formatting.None;
        }

        public override void ExecuteResult(ControllerContext context)
        {
            context.HttpContext.Response.Clear();
            context.HttpContext.Response.ContentType = MimeType;

            using (var writer = new XmlTextWriter(context.HttpContext.Response.OutputStream, Encoding.UTF8) { Formatting = Formatting })
                _document.WriteTo(writer);
        }
    }

我相信这是我的第一个问题所在。我想在序列化的ViewModel对象中创建一个XDocument - 在这种情况下为t - 使用XmlResult类,但我收到错误说&#34;数据在根级别无效。第1行,第1位。&#34;这告诉我XDocument类在解析序列化的ViewModel对象时遇到问题。我在这做错了什么?

接下来,我尝试在XDocument中保存MemoryStream(在成功创建之后)。我们的想法是从byte对象构建一个StringBuilder数组,该对象通过XDocument访问MemoryStream中保存的StreamReader,并发送该数组通过HttpWebRequest对象到远程服务器。但是,由于上述错误,我还没有到目前为止。

非常感谢任何帮助。如果需要,我愿意改变这整个方法。即使我让第一部分工作,我也不确定后一部分是否有效,所以任何建议都会得到注意。谢谢。

更新:有关例外的更多信息

此行正在抛出异常:

XDocument xdoc = XDocument.Parse(xrs.ToString());

innerException为空。 Message是&#34;根级别的数据无效。第1行,第1位。&#34;

1 个答案:

答案 0 :(得分:1)

public async Task<ActionResult> Index(Transmission t)
    {
        ViewBag.ErrorMessage = "";
        ViewBag.OtherMessage = "";

        try
        {

            var xmlSerializer = new XmlSerializer(typeof(Transmission));
            using (StringWriter sw = new StringWriter())
            {
                xmlSerializer.Serialize(sw, t);
                var contentData = sw.ToString();
                var httpContent = new StringContent(contentData, Encoding.UTF8, "application/xml");
                var httpClient = new HttpClient();
                httpClient.Timeout = new TimeSpan(0, 1, 0);
                var response = await httpClient.PostAsync("", httpContent);
                ViewBag.OtherMessage = await response.Content.ReadAsStringAsync();
                return View("Error"); //TODO: change this to success when I get the 500 error fixed
            }
        }
        catch (Exception ex)
        {
            string message = ex.Message;
            ViewBag.ErrorMessage = ex.Message;
            return View("Error");
        }
    }