Reputation: 711
I have an ASP.NET MVC 5 application in which I am trying to serialize my ViewModel and send it to a remote, third-party server for data processing. I am not exactly sure what I'm doing wrong, but below is the code that I have tried.
Firstly, here is the POST
method in my controller in which I am trying to serialize the ViewModel and send it to the remote server:
[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");
}
}
}
As you can see above, I am using two classes, called XmlActionResult
and XmlResult
, respectively. The XmlResult
class is being used to serialize the ViewModel. Here is the implementation of the XmlResult
class:
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);
}
}
}
After the XmlResult
class serializes the ViewModel, I am attempting to create a XDocument
using the XmlActionResult
class. Here is the implementation of the XmlActionResult
class:
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);
}
}
I believe this is where my first problem lies. I want to create a XDocument
from the serialized ViewModel object -- t
in this case -- using the XmlResult
class, but I am getting an error saying "Data at the root level is invalid. Line 1, position 1. " This tells me that the XDocument
class is having a problem parsing the serialized ViewModel object. What have I done wrong here?
Next, I am trying to save the XDocument
(after it has been successfully created) in a MemoryStream
. The idea is to build a byte
array from a StringBuilder
object that is accessing the XDocument
that is saved in the MemoryStream
via a StreamReader
, and send that to the remote server via the HttpWebRequest
object. However, I haven't gotten this far yet, thanks to the above error.
Any help is greatly appreciated. I'm willing to change this entire approach if I need to. I'm not certain the latter part will work even if I get the first part working, so any advice will be heeded. Thank you.
Update: Further Information about Exception
The exception is being thrown at this line:
XDocument xdoc = XDocument.Parse(xrs.ToString());
The innerException
is null.
The Message
is "Data at the root level is invalid. Line 1, position 1."
Upvotes: 0
Views: 1090
Reputation: 1603
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");
}
}
Upvotes: 2