سؤال

I am writing a media type formatter for HTML to automatically generate a Razor view based on an html request from the user. I am doing this for use inside a SelfHosted service. I need to detect what controller/action was requested to allow me to pick the view to render into.

 public class RazorHtmlMediaTypeFormatter : MediaTypeFormatter
    {
        public RazorHtmlMediaTypeFormatter()
        {
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
        }

        public override bool CanWriteType(Type type)
        {
            return true;
        }

        public override bool CanReadType(Type type)
        {
            return false;
        }

        public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContentHeaders contentHeaders, System.Net.TransportContext transportContext)
        {
            return Task.Factory.StartNew(() =>
                {
                    var view = Razor.Resolve(String.Format("{0}.{1}.cshtml", something.Controller, something.Action), value);

                    byte[] buf = System.Text.Encoding.Default.GetBytes(view.Run(new ExecuteContext()));
                    stream.Write(buf, 0, buf.Length);
                    stream.Flush();
                });
        }
    }
هل كانت مفيدة؟

المحلول

Web API Contrib has a working RazorViewFormatter in here.

نصائح أخرى

Why not wrapping your returned objects in Metadata<T>?

I.e. return, instead of MyCustomObject, Metadata<MyCustomObject>. As Metadata properties, you can set controller name and action. Then in the formatter, just decouple the Metadata and your custom object, and serialize just that custom object.

I blogged about this approach here - http://www.strathweb.com/2012/06/extending-your-asp-net-web-api-responses-with-useful-metadata/. While the purpose of the article is a bit different, I am sure you can relate it to your needs.

Edit: or if you are OK with a small hack, use a custom filter and headers:

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        actionContext.Response.Headers.Add("controller", actionContext.ActionDescriptor.ControllerDescriptor.ControllerName);
        actionContext.Response.Headers.Add("action", actionContext.ActionDescriptor.ActionName;);
        base.OnActionExecuting(actionContext);
    }

then just read it from the headers in the formatter, and remove the header entries so that they don't get sent to the client.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top