0

我在从 web api 控制器返回 css 时遇到问题。该代码接受一个 css 文件的请求,并在从数据库中读取它后返回它。

问题是 web api 代码似乎正在序列化响应并返回它而不是 css 本身。

在这里,您可以看到浏览器发送到服务器的链接标签,该标签应该返回 css。您还可以看到响应看起来像是我的 css 的序列化,而不仅仅是 css 字符串。

在此处输入图像描述

我的请求和响应标头:

在此处输入图像描述

我的控制器如下所示:

public HttpResponseMessage Get(string fileName, string siteId, int id)
{
    var fileData = ReadSomeCssFromTheDatabase();

    var result = new HttpResponseMessage(HttpStatusCode.OK);
    result.Content = new ByteArrayContent(fileData);
    result.Content.Headers.ContentType = new MediaTypeHeaderValue("text/css");

    result.Headers.CacheControl = new CacheControlHeaderValue();
    result.Headers.CacheControl.MaxAge = TimeSpan.FromHours(0);
    result.Headers.CacheControl.MustRevalidate = true;

    return result;
}

安装了一个“text/css”格式化程序,正在创建但由于某种原因没有被命中。

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

    public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
    {
        var taskCompletionSource = new TaskCompletionSource<object>();
        try
        {
            var memoryStream = new MemoryStream();
            readStream.CopyTo(memoryStream);
            var s = System.Text.Encoding.UTF8.GetString(memoryStream.ToArray());
            taskCompletionSource.SetResult(s);
        }
        catch (Exception e)
        {
            taskCompletionSource.SetException(e);
        }
        return taskCompletionSource.Task;
    }

    public override bool CanReadType(Type type)
    {
        return type == typeof(string);
    }

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

我究竟做错了什么?

4

1 回答 1

1
  • 您的格式化程序不会受到打击,因为您没有经历内容协商过程(因为您在操作中返回 HttpResponseMessage ......您可以使用 Request.CreateResponse<> 使 conneg 过程运行)

  • 您正在尝试“写入”css 内容,对吗?...但我看到 CanWriteType 正在返回“false”,而且您似乎正在覆盖 ReadFromStreamAsync 而不是 WriteToStreamAsync?

你可以如何做的一个例子(根据我对上述场景的理解):

public class DownloadFileInfo
{
    public string FileName { get; set; }
    public string SiteId { get; set; }
    public int Id { get; set; }

}

public HttpResponseMessage Get([FromUri]DownloadFileInfo info)
    {
        // validate the input

        //Request.CreateResponse<> would run content negotiation and get the appropriate formatter
        //if you are asking for text/css in Accept header OR if your uri ends with .css extension, you should see your css formatter getting picked up.
        HttpResponseMessage response = Request.CreateResponse<DownloadFileInfo>(HttpStatusCode.OK, info);

        response.Headers.CacheControl = new CacheControlHeaderValue();
        response.Headers.CacheControl.MaxAge = TimeSpan.FromHours(0);
        response.Headers.CacheControl.MustRevalidate = true;

        return response;
    }

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

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

    public override bool CanWriteType(Type type)
    {
        return type == typeof(DownloadFileInfo);
    }

    public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
    {
        //use the 'value' having DownloadFileInfo object to get the details from the database.
        // Fead from database and if you can get it as a Stream, then you just need to copy it to the 'writeStream'
    }
}
于 2012-08-22T00:20:09.037 回答