Language: C#
MVC API Controller that allows for format=xml/json
using System; using System.Collections.Generic; using System.Web; using System.Web.Mvc; using Westwind.Utilities; using System.ServiceModel.Syndication; using CodePasteBusiness; using System.Text; using System.Collections; using System.IO; using System.Xml; using Westwind.Web.JsonSerializers; namespace CodePasteMvc.Controllers { /// <summary> /// API controller that handles results based. /// /// Reusable base class. /// </summary> public class ApiControllerBase : baseController { /// <summary> /// Used to determine output format - json,xml,rss,atom /// </summary> protected string Format = string.Empty; protected override void Initialize(System.Web.Routing.RequestContext requestContext) { // Create a custom Invoker that handles non-actionresult controller methods this.ActionInvoker = new ApiActionInvoker(); base.Initialize(requestContext); // pick up the format this.Format = (Request.QueryString["Format"] ?? string.Empty).ToLower(); //if (string.IsNullOrEmpty(this.Format)) // this.Format = "xml"; } /// <summary> /// Checks /// </summary> /// <param name="instance"></param> /// <returns></returns> protected internal virtual ActionResult ApiResult(object instance) { if (string.IsNullOrEmpty(this.Format)) return null; if (this.Format == "json") return this.Json(instance); else if (this.Format == "xml") { string xmlResult = string.Empty; if (!SerializationUtils.SerializeObject(instance, out xmlResult)) throw new InvalidOperationException("Unable to serialize instance to Xml"); return this.Content(xmlResult, "text/xml", Encoding.UTF8); } else if (this.Format == "rss" || this.Format == "atom") { return GetFeed(instance); } return null; } /// <summary> /// Returns and rss or atom feed /// </summary> /// <param name="instance"></param> /// <returns></returns> protected internal ActionResult GetFeed(object instance) { string title = "CodePaste.NET"; string action = this.RouteData.Values["listAction"] as string; if (string.IsNullOrEmpty(action)) action = this.RouteData.Values["Action"] as string ?? string.Empty; action = action.ToLower(); if (action == "recent") title = "CodePaste.NET Recent Snippets"; else if (action == "mysnippets") title = "CodePaste.NET - My Snippets"; SyndicationFeed feed = new SyndicationFeed(title, "Paste and Link .NET Code", new Uri(Request.Url.AbsoluteUri)); feed.BaseUri = new Uri("http://codepaste.net/recent"); feed.LastUpdatedTime = DateTime.Now; busCodeSnippet snippet = new busCodeSnippet(); List<SyndicationItem> feedItems = new List<SyndicationItem>(); foreach (CodeSnippetListItem item in (IEnumerable)instance) { SyndicationItem rssItem = new SyndicationItem() { Id = item.Id, Title = SyndicationContent.CreateHtmlContent(item.Title), Content = SyndicationContent.CreateHtmlContent( "\r\n<link href=\"" + WebUtils.ResolveServerUrl("~/css/csharp.css") + "\" rel=\"stylesheet\" type=\"text/css\" />\r\n" + "<pre>" + snippet.GetFormattedCode(item.Code, item.Language, item.ShowLineNumbers) + "</pre>"), PublishDate = item.Entered }; rssItem.Authors.Add(new SyndicationPerson("", item.Author, null)); rssItem.Links.Add(new SyndicationLink(new Uri(WebUtils.GetFullApplicationPath() + "/" + item.Id), "alternate", item.Title, "text/html", 1000)); feedItems.Add(rssItem); } feed.Items = feedItems; MemoryStream ms = new MemoryStream(); XmlWriter writer = XmlWriter.Create(ms); if (this.Format == "rss") { Rss20FeedFormatter rssFormatter = new Rss20FeedFormatter(feed); rssFormatter.WriteTo(writer); } else { Atom10FeedFormatter atomFormatter = new Atom10FeedFormatter(feed); atomFormatter.WriteTo(writer); } writer.Flush(); ms.Position = 0; return this.Content(Encoding.UTF8.GetString(ms.ToArray()), "application/xml"); } /// <summary> /// Parses a single object value from the Request input stream into the /// specified type /// </summary> /// <param name="dataType"></param> /// <returns></returns> protected internal object ParseObjectFromPostData(Type dataType) { StreamReader sr = new StreamReader(Request.InputStream); string data = sr.ReadToEnd(); sr.Close(); object result = null; if (Request.ContentType == "text/javascript" || Request.ContentType == "application/json") { JSONSerializer ser = new JSONSerializer(SupportedJsonParserTypes.WestWindJsonSerializer); result = ser.Deserialize(data, dataType); } else if (Request.ContentType == "text/xml") { result = SerializationUtils.DeSerializeObject(data, dataType); } else return ExceptionResult("Unsuppported data input format. Please provide input content-type as text/javascript, application/json or text/xml."); return result; } /// <summary> /// Ensure that exceptions are returned in the API format /// Excpetion is rendered as a Callback Exception /// </summary> /// <param name="filterContext"></param> protected override void OnException(ExceptionContext filterContext) { base.OnException(filterContext); // only handle API results here: Format must be set // otherwise fall through and return if (string.IsNullOrEmpty(this.Format)) return; Response.StatusCode = 500; Westwind.Web.CallbackException exception = new Westwind.Web.CallbackException(); exception.message = filterContext.Exception.Message; if (HttpContext.IsDebuggingEnabled) exception.stackTrace = filterContext.Exception.StackTrace; exception.isCallbackError = true; filterContext.Result = this.ApiResult(exception); filterContext.ExceptionHandled = true; } protected ActionResult ExceptionResult(Exception ex) { Response.StatusCode = 500; Westwind.Web.CallbackException exception = new Westwind.Web.CallbackException(); exception.message = ex.Message; if (HttpContext.IsDebuggingEnabled) exception.stackTrace = ex.StackTrace; exception.isCallbackError = true; // return result based on ?Format= return this.ApiResult(exception); } protected ActionResult ExceptionResult(string message) { Response.StatusCode = 500; Westwind.Web.CallbackException exception = new Westwind.Web.CallbackException(); exception.message = message; exception.isCallbackError = true; // return result based on ?Format= return this.ApiResult(exception); } } /// <summary> /// Custom ActionInvoker that allows Controller methods to return plain /// value results rather than action results that are formatted using /// API formatting rules of an API Controller /// </summary> public class ApiActionInvoker : ControllerActionInvoker { /// <summary> /// Overrides output creation if the result from a controller /// method doesn't return an ActionResult. Instead it turns the /// result into the appropriate API response. /// </summary> /// <param name="controllerContext"></param> /// <param name="actionDescriptor"></param> /// <param name="actionReturnValue"></param> /// <returns></returns> protected override ActionResult CreateActionResult(ControllerContext controllerContext, ActionDescriptor actionDescriptor, object actionReturnValue) { // Allow for controllers to return plain values rather than an action result // Also handles exceptions from API controller if (!(actionReturnValue is ActionResult) && controllerContext.Controller is ApiControllerBase) { ApiController controller = controllerContext.Controller as ApiController; // Generate API results in XML/JSON return controller.ApiResult(actionReturnValue); } // Process as normal request return base.CreateActionResult(controllerContext, actionDescriptor, actionReturnValue); } } }
Tags:
Report Abuse
Subscribe
Discuss
What's new
What is it
New Snippet
Recent Snippets
My Snippets
Web Code
Search

