有没有一种方法可以强制ASP.NET Web API返回纯文本?


125

我需要从ASP.NET Web API控制器获得纯文本格式的响应。

我尝试用发出请求,Accept: text/plain但似乎没有成功。此外,该请求是外部的,不受我的控制。我要完成的是模仿旧的ASP.NET方法:

context.Response.ContentType = "text/plain";
context.Response.Write("some text);

有任何想法吗?

编辑,解决方案:基于Aliostad的回答,我添加了WebAPIContrib文本格式化程序,并在Application_Start中对其进行了初始化:

  config.Formatters.Add(new PlainTextFormatter());

然后我的控制器出现了类似以下内容:

[HttpGet, HttpPost]
public HttpResponseMessage GetPlainText()
{
  return ControllerContext.Request.CreateResponse(HttpStatusCode.OK, "Test data", "text/plain");
}

Answers:


231

嗯...我认为您无需创建自定义格式程序即可完成此工作。而是返回如下内容:

    [HttpGet]
    public HttpResponseMessage HelloWorld()
    {
        string result = "Hello world! Time is: " + DateTime.Now;
        var resp = new HttpResponseMessage(HttpStatusCode.OK);
        resp.Content = new StringContent(result, System.Text.Encoding.UTF8, "text/plain");
        return resp;
    }

这对我有效,而无需使用自定义格式化程序。

如果您明确想要创建输出并基于“接受”标头覆盖默认的内容协商,则您将不想使用Request.CreateResponse()它,因为它会强制使用mime类型。

而是显式创建一个新文件HttpResponseMessage并手动分配内容。上面的示例使用了该方法,StringContent但是还有很多其他内容类可用于从各种.NET数据类型/结构返回数据。


1
实际上,这就是我所追求的解决方案,因为我的API将JSON对象返回到所有方法的99%,只有少数(很少)方法需要纯字符串响应(对于许多方法,我使用MemoryStream返回数据仅在2或3种方法中,我没有返回.NET字符串,而它是作为JSON字符串返回的。您的回答,恕我直言,是针对此问题的KISS响应(尽管不是100%DRY,但我只是写了一个扩展方法来实现此目的... :-)很好!)StringContent非常好。谢谢。
Loudenvier 2013年

有许多自定义XXXContent类可创建特定类型的内容,从而使这种事情变得非常简单。
里克·斯特拉尔

我看到这种方法的正确答案。但是,HttpContext.Current现在为null。有什么想法吗?
Nachiket Mehta

@JavascriptEnthusiast-HttpContext.Current为null最有可能是因为您是自托管的,或者是在没有System.Web管道的情况下通过OWin堆栈运行的。与此解决方案无关。
里克·斯特拉尔

15

如果您只是在寻找简单的纯文本格式设置器而没有添加其他依赖项,那么这应该可以解决问题。

public class TextPlainFormatter : MediaTypeFormatter
{
    public TextPlainFormatter()
    {
        this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));
    }

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

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

    public override Task WriteToStreamAsync(Type type, object value, Stream stream, HttpContentHeaders contentHeaders, TransportContext transportContext)
    {
        return Task.Factory.StartNew(() => {
            StreamWriter writer = new StreamWriter(stream);
            writer.Write(value);
            writer.Flush();
        });
    }

    public override Task<object> ReadFromStreamAsync(Type type, Stream stream, HttpContentHeaders contentHeaders, IFormatterLogger formatterLogger)
    {
        return Task.Factory.StartNew(() => {
            StreamReader reader = new StreamReader(stream);
            return (object)reader.ReadToEnd();
        });
    }
}

不要忘记将其添加到您的Global Web API配置中。

config.Formatters.Add(new TextPlainFormatter());

现在您可以将字符串对象传递给

this.Request.CreateResponse(HttpStatusCode.OK, "some text", "text/plain");

12
  • 请注意不要在ASP.NET Web API中使用上下文,否则您迟早会感到抱歉。ASP.NET Web API的异步性质导致使用HttpContext.Current责任。
  • 使用纯文本格式器,然后将其添加到格式器中。周围有几十个。您甚至可以轻松编写自己的内容。WebApiContrib有一个。
  • 如果已注册纯文本格式器,则可以httpResponseMessage.Headers通过text/plain在控制器中将内容类型标头设置为on 来强制执行此操作。

不用担心,我既不暗示也不打算使用HttpContext对象,我只是添加了它以说明如何在经典的ASP.NET中实现它
Magnus Johansson

好吧,waddayknow,我已经引用了WebAPIContrib,有时很简单。
Magnus Johansson

@Magnus当然。实际上,在我阅读所写内容之后,我改变了措辞。但是读另一个答案让我强调了第一点。
Aliostad

您说的不是使用HttpContext.Current,还有哪些替代方法?
surya 2013年

@spiderdevil是的,这绝对是我的意思。您不需要它,直接传递请求/响应/配置。
Aliostad


6

当接受:文本/纯文本不起作用时,则没有针对文本mime类型的注册格式器。

通过从服务配置中获取所有受支持的格式化程序的列表,可以确保没有用于指定的mime类型的格式化程序。

创建一个非常简单的支持文本mime类型的媒体类型格式化程序。

http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters


希望我也能接受您的答案,接受的答案使我免于编写自己的格式化程序的麻烦。至少+1。
Magnus Johansson

0

像下面这样的扩展可以减少行数并美化您的代码:

public static class CommonExtensions
{
    public static HttpResponseMessage ToHttpResponseMessage(this string str)
    {
        var resp = new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new StringContent(str, System.Text.Encoding.UTF8, "text/plain")
        };

        return resp;
    }
}


现在,您可以在中使用定义的扩展名Web API

public class HomeController : ApiController
{
    [System.Web.Http.HttpGet]
    public HttpResponseMessage Index()
    {
        return "Salam".ToHttpResponseMessage();
    }
}


通过路由,{DOMAIN}/api/Home/Index您可以看到以下纯文本:

MyPlainTextResponse


不要将字符串名称空间浪费在与字符串无关的东西上。
Rambalac
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.