How to pass XML as POST to an ActionResult in ASP MVC .NET
@Freddy - liked your approach and improved on it with the following code to simplify stream reading:
public override void OnActionExecuting(ActionExecutingContext filterContext) { HttpContextBase httpContext = filterContext.HttpContext; if (!httpContext.IsPostNotification) { throw new InvalidOperationException("Only POST messages allowed on this resource"); } Stream httpBodyStream = httpContext.Request.InputStream; if (httpBodyStream.Length > int.MaxValue) { throw new ArgumentException("HTTP InputStream too large."); } StreamReader reader = new StreamReader(httpBodyStream, Encoding.UTF8); string xmlBody = reader.ReadToEnd(); reader.Close(); filterContext.ActionParameters["message"] = xmlBody; // Sends XML Data To Model so it could be available on the ActionResult base.OnActionExecuting(filterContext); }
Then in the Controller you can access the xml as a string:
[RestAPIAttribute] public ActionResult MyActionResult(string message) { }
This could be accomplished by using the ActionFilterAttribute. Action Filters basically intersects the request before or after the Action Result. So I just built a custom action filter attribute for POST Action Result. Here is what I did:
public class RestAPIAttribute : ActionFilterAttribute{ public override void OnActionExecuting(ActionExecutingContext filterContext) { HttpContextBase httpContext = filterContext.HttpContext; if (!httpContext.IsPostNotification) { throw new InvalidOperationException("Only POST messages allowed on this resource"); } Stream httpBodyStream = httpContext.Request.InputStream; if (httpBodyStream.Length > int.MaxValue) { throw new ArgumentException("HTTP InputStream too large."); } int streamLength = Convert.ToInt32(httpBodyStream.Length); byte[] byteArray = new byte[streamLength]; const int startAt = 0; /* * Copies the stream into a byte array */ httpBodyStream.Read(byteArray, startAt, streamLength); /* * Convert the byte array into a string */ StringBuilder sb = new StringBuilder(); for (int i = 0; i < streamLength; i++) { sb.Append(Convert.ToChar(byteArray[i])); } string xmlBody = sb.ToString(); //Sends XML Data To Model so it could be available on the ActionResult base.OnActionExecuting(filterContext); }}
Then on the action result method on your controller you should do something like this:
[RestAPIAttribute] public ActionResult MyActionResult() { //Gets XML Data From Model and do whatever you want to do with it }
Hope this helps somebody else, if you think there are more elegant ways to do it, let me know.
Why can they not pass the xml as a string in the form post?
Example:
public ActionResult SendMeXml(string xml){ //Parse into a XDocument or something else if you want, and return whatever you want. XDocument xmlDocument = XDocument.Parse(xml); return View();}
You could create a form post and send it in a single form field.