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

C# 如何将ViewModel序列化为XML并将其发送到远程服务器?,c#,xml,asp.net-mvc,http,serialization,C#,Xml,Asp.net Mvc,Http,Serialization,我有一个ASP.NET MVC 5应用程序,我试图在其中序列化我的ViewModel并将其发送到远程第三方服务器进行数据处理。我不确定我做错了什么,但下面是我尝试过的代码 首先,这里是控制器中的POST方法,在该方法中,我尝试序列化ViewModel并将其发送到远程服务器: [HttpPost] public ActionResult Index(Transmission t) { ViewBag.ErrorMessage = "";

我有一个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");
            }
        }
    }
正如您在上面看到的,我使用了两个类,分别称为
XmlActionResult
XmlResult
XmlResult
类用于序列化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);
            }
        }
    }
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);
        }
    }
我相信这是我的第一个问题所在。我想使用
XmlResult
类从序列化的ViewModel对象创建
XDocument
,在本例中,使用
XmlResult
类创建一个
XDocument
,但我收到一个错误,提示“根级别的数据无效。第1行,位置1。”这说明
XDocument
类在解析序列化的ViewModel对象时遇到问题。我做错了什么

接下来,我尝试将
XDocument
(成功创建后)保存在
内存流中。其思想是从一个
StringBuilder
对象构建一个
byte
数组,该对象通过
StreamReader
访问
XDocument
,该文档保存在
MemoryStream
中,并通过
HttpWebRequest
对象将其发送到远程服务器。然而,由于上面的错误,我还没有走到这一步

非常感谢您的帮助。如果需要,我愿意改变整个方法。我不确定后一部分是否会起作用,即使我让前一部分起作用,所以任何建议都会得到重视。多谢各位

更新:有关异常的更多信息

正在此行引发异常:

XDocument xdoc = XDocument.Parse(xrs.ToString());
innerException
为空。
消息是“根级别的数据无效。第1行,位置1。”

公共异步任务索引(传输t)
{
ViewBag.ErrorMessage=“”;
ViewBag.OtherMessage=“”;
尝试
{
var xmlSerializer=新的xmlSerializer(typeof(传输));
使用(StringWriter sw=new StringWriter())
{
serializer.Serialize(sw,t);
var contentData=sw.ToString();
var httpContent=newstringcontent(contentData,Encoding.UTF8,“application/xml”);
var httpClient=新的httpClient();
httpClient.Timeout=新的时间跨度(0,1,0);
var response=wait-httpClient.PostAsync(“,httpContent”);
ViewBag.OtherMessage=wait response.Content.ReadAsStringAsync();
return View(“Error”);//TODO:在修复500错误后将此更改为success
}
}
捕获(例外情况除外)
{
字符串消息=例如消息;
ViewBag.ErrorMessage=例如消息;
返回视图(“错误”);
}
}
公共异步任务索引(传输t)
{
ViewBag.ErrorMessage=“”;
ViewBag.OtherMessage=“”;
尝试
{
var xmlSerializer=新的xmlSerializer(typeof(传输));
使用(StringWriter sw=new StringWriter())
{
serializer.Serialize(sw,t);
var contentData=sw.ToString();
var httpContent=newstringcontent(contentData,Encoding.UTF8,“application/xml”);
var httpClient=新的httpClient();
httpClient.Timeout=新的时间跨度(0,1,0);
var response=wait-httpClient.PostAsync(“,httpContent”);
ViewBag.OtherMessage=wait response.Content.ReadAsStringAsync();
return View(“Error”);//TODO:在修复500错误后将此更改为success
}
}
捕获(例外情况除外)
{
字符串消息=例如消息;
ViewBag.ErrorMessage=例如消息;
返回视图(“错误”);
}
}

根级别的数据无效。第1行,位置1。-您能否共享异常的完整
ToString()
输出,包括异常类型、消息、回溯和内部异常?在哪一行抛出异常?你能把你的问题简化成一个问题吗?@dbc当然可以。请稍候。@dbc已提供有关异常的详细信息。请将xrs.ToString()放入变量中,以查看XDocument试图解析的内容。XmlResult执行此操作,它只写入http响应流。根级别的数据无效。第1行,位置1。-您能否共享异常的完整
ToString()
输出,包括异常类型、消息、回溯和内部异常?在哪一行抛出异常?你能把你的问题简化成一个问题吗?@dbc当然可以。请稍候。@dbc已提供有关异常的详细信息。请将xrs.ToString()放入变量中,以查看XDocument试图解析的内容。XmlResult执行此操作,它只写入http响应流。这是正确的解决方案。我只需要做一些更改,这样XML编码就不会出现在XML数据中,但这是正确的。非常感谢。“这非常有帮助。”弗兰是对的。我做了很多XmlSerializer会为我做的事情。我误解了
XmlResult
XmlActionResult
类在做什么。事实证明,我根本不需要这些。这是正确的解决方案。我只需要做一些更改,这样XML编码就不会出现在XML数据中,但这是正确的。非常感谢。“这非常有帮助。”弗兰是对的。我做了很多XmlSerializer会为我做的事情。我误解了
XmlResult
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");
        }
    }