Чи є спосіб змусити веб-API ASP.NET повернути звичайний текст?


125

Мені потрібно повернути відповідь у простому тексті від контролера веб-API ASP.NET.

Я спробував зробити запит, Accept: text/plainале, схоже, це не робити. Крім того, запит є зовнішнім і поза моїм контролем. Що я хотів би зробити, це наслідувати старий спосіб ASP.NET:

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

Будь-які ідеї?

EDIT, рішення : На основі відповіді Aliostad я додав текстовий формат WebAPIContrib , ініціалізував його у Application_Start:

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

і мій контролер закінчив щось на кшталт:

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

Відповіді:


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;
    }

Це працює для мене без використання спеціального форматера.

Якщо ви явно хочете створити вихід і замінити узгодження контенту за замовчуванням на основі заголовків Accept, ви не хочете користуватися, Request.CreateResponse()оскільки це змушує тип mime.

Замість цього явно створіть новий HttpResponseMessageі призначте вміст вручну. У наведеному вище прикладі використовується, StringContentале існує досить багато інших класів вмісту для повернення даних з різних типів / структур .NET.


1
Насправді це рішення, для якого я пішов, оскільки мій API повертав JSON-об’єкти до 99% усіх методів, лише на кілька (дуже мало) методів знадобиться відповідь простого рядка (і для багатьох із них я використовую MemoryStream для повернення даних безпосередньо у відповіді, так що це не питання.) Лише за допомогою 2 або 3 методів я повернув рядок .NET, і він повертався як рядок JSON. Ваша відповідь, IMHO, - відповідь KISS на цю проблему (хоча це не 100% сухий, але я просто написав метод розширення для рядка, щоб це зробити ... :-) Приємно!) StringContent дуже приємний. Дякую.
Loudenvier

Існує декілька спеціальних класів XXXContent для створення конкретних типів вмісту, які роблять подібні речі досить прямими.
Рік Страль

Я бачу правильну відповідь при такому підході. Однак HttpContext.Current зараз недійсний. Будь-які ідеї з цього приводу?
Начікет Мехта

@Ja JavaScriptEnthusiast - HttpContext.Current є нульовим, швидше за все, тому що ви самостійно розміщуєте хостинг або працюєте через стек OWin без конвеєра System.Web. Однак, не пов'язане з цим рішенням.
Рік Страль

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();
        });
    }
}

Не забудьте додати його до глобальної конфігурації веб-api.

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

Тепер ви можете передавати рядкові об’єкти

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


12
  • Будьте обережні, щоб не використовувати контекст у веб-API ASP.NET, інакше ви рано чи пізно будете шкодувати. Асинхронний характер веб-API ASP.NET обумовлює використання HttpContext.Currentвідповідальності.
  • Використовуйте звичайний текстовий формат і додайте до своїх форматів. Їх навколо десятки. Ви навіть могли легко написати своє. У WebApiContrib є один.
  • Ви можете змусити його установку заголовка типу контенту на , httpResponseMessage.Headersщоб text/plainв вашому контролері при умови , що ви зареєстровані простий форматування тексту.

Не хвилюйтесь, я ні мав на увазі, ні мав намір використовувати об’єкт HttpContext, я просто додав його, щоб проілюструвати, як би це зробити у класичному ASP.NET
Magnus Johansson

Ну, waddayknow, я вже посилався на WebAPIContrib, іноді це просто.
Магнус Йоханссон

@Magnus Sure. Я фактично змінив формулювання після того, як прочитав те, що написав. Але читання іншої відповіді змусило мене наголосити на першому моменті.
Аліостад

Ви скажете не використовувати HttpContext.Current, які є альтернативи?
surya

@spiderdevil так, це абсолютно те, що я говорю. Вам це не потрібно, передайте запит / відповідь / конфігурацію безпосередньо.
Аліостад

6

Якщо Accept: text / plain не працює, тоді немає зареєстрованого форматера для типів mime.

Ви можете переконатися у відсутності форматорів для вказаного типу mime, отримавши список усіх підтримуваних форматів із конфігурації послуги.

Створіть дуже простий формат медіа-типу, який підтримує текстові типи mime.

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


Хотілося б, щоб я також міг прийняти вашу відповідь, прийнята відповідь врятувала мені проблеми написання власного форматера. +1 принаймні
Магнус Йоханссон

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


Не витрачайте на простір імен рядків речі, не пов'язані з рядком.
Рамбалак
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.