Apakah ada cara untuk memaksa ASP.NET Web API mengembalikan teks biasa?

125

Saya perlu mendapatkan tanggapan kembali dalam teks biasa dari pengontrol API Web ASP.NET.

Saya telah mencoba melakukan permintaan Accept: text/plaintetapi tampaknya tidak berhasil. Selain itu, permintaan tersebut bersifat eksternal dan di luar kendali saya. Apa yang akan saya capai adalah meniru cara ASP.NET lama:

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

Ada ide?

EDIT, solusi : Berdasarkan jawaban Aliostad, saya menambahkan formatter teks WebAPIContrib , menginisialisasinya di Application_Start:

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

dan pengontrol saya berakhir seperti:

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

Jawaban:

231

Hmmm ... Saya rasa Anda tidak perlu membuat formatter kustom untuk membuat ini berfungsi. Sebaliknya kembalikan konten seperti ini:

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

Ini berfungsi untuk saya tanpa menggunakan formatter kustom.

Jika Anda secara eksplisit ingin membuat output dan menimpa negosiasi konten default berdasarkan header Terima, Anda tidak akan ingin menggunakan Request.CreateResponse()karena memaksa jenis mime.

Alih-alih secara eksplisit buat yang baru HttpResponseMessagedan tetapkan konten secara manual. Contoh di atas menggunakan StringContenttetapi ada beberapa kelas konten lain yang tersedia untuk mengembalikan data dari berbagai tipe / struktur data .NET.

Rick Strahl
sumber
1
Ini sebenarnya adalah solusi yang saya gunakan karena API saya akan mengembalikan objek JSON ke 99% dari semua metode, hanya beberapa (sangat sedikit) metode yang memerlukan respons string biasa (dan untuk banyak di antaranya saya menggunakan MemoryStream untuk mengembalikan data langsung di respons jadi itu bukan masalah.) Hanya dalam 2 atau 3 metode saya mengembalikan string .NET, dan itu dikembalikan sebagai string JSON. Jawaban Anda, IMHO, adalah jawaban KISS untuk masalah ini (meskipun tidak 100% KERING, tetapi saya baru saja menulis metode ekstensi untuk melakukan itu ... :-) Bagus!) StringContent sangat bagus. Terima kasih.
Loudenvier
Ada sejumlah kelas XXXContent khusus untuk membuat jenis konten tertentu yang membuat hal semacam ini cukup mudah.
Rick Strahl
Saya melihat tanggapan yang benar dengan pendekatan ini. Namun, HttpContext.Current sekarang null. Ada ide tentang ini?
Nachiket Mehta
@JavascriptEnthusiast - HttpContext.Current nihil kemungkinan besar karena Anda menghosting sendiri atau menjalankan tumpukan OWin tanpa pipeline System.Web. Tidak terkait dengan solusi ini.
Rick Strahl
15

Jika Anda hanya mencari pemformat polos / teks sederhana tanpa menambahkan dependensi tambahan, ini harus dilakukan.

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

Jangan lupa untuk menambahkannya ke konfigurasi api web Global Anda.

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

Sekarang Anda dapat mengirimkan objek string ke

this.Request.CreateResponse(HttpStatusCode.OK, "some text", "text/plain");
Despertar
sumber
12
  • Harap berhati-hati untuk tidak menggunakan konteks dalam ASP.NET Web API atau Anda akan menyesal cepat atau lambat. Sifat asynchronous dari ASP.NET Web API membuat penggunaan HttpContext.Currentkewajiban.
  • Gunakan pemformat teks biasa dan tambahkan ke pemformat Anda. Ada lusinan di sekitar. Anda bahkan dapat menulis milik Anda dengan mudah. WebApiContrib punya satu.
  • Anda dapat memaksanya dengan menyetel header jenis konten httpResponseMessage.Headerske text/plaindi pengontrol Anda asalkan Anda telah mendaftarkan pemformat teks biasa.
Aliostad
sumber
Jangan khawatir, saya tidak tersirat atau bermaksud menggunakan objek HttpContext, saya hanya menambahkannya untuk menggambarkan bagaimana seseorang akan melakukannya di ASP.NET klasik
Magnus Johansson
Yah, tahu, saya sudah punya referensi WebAPIContrib, terkadang sederhana.
Magnus Johansson
@BenarSusu Saya sebenarnya mengubah kata-katanya setelah saya membaca apa yang saya tulis. Tetapi membaca jawaban lain membuat saya menekankan poin pertama itu.
Aliostad
Anda mengatakan untuk tidak menggunakan HttpContext.Current, apa alternatifnya?
surya
@ spiderdevil ya, itu benar-benar apa yang saya katakan. Anda tidak memerlukannya, berikan permintaan / respons / konfigurasi secara langsung.
Aliostad
6

Jika Terima: teks / biasa tidak berfungsi, maka tidak ada pemformat terdaftar untuk jenis mime teks.

Anda dapat memastikan bahwa tidak ada pemformat untuk jenis mime yang ditentukan dengan mendapatkan daftar semua pemformat yang didukung dari konfigurasi layanan.

Buat formatter jenis media yang sangat mudah yang mendukung jenis teks mime.

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

Regfor
sumber
Seandainya saya bisa menerima jawaban Anda juga, jawaban yang diterima menyelamatkan saya dari masalah menulis formatter saya sendiri. +1 setidaknya.
Magnus Johansson
0

Ekstensi seperti berikut ini dapat mengurangi jumlah baris dan mempercantik kode Anda:

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


Sekarang Anda dapat menggunakan ekstensi yang ditentukan di Web API:

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


Dengan perutean {DOMAIN}/api/Home/IndexAnda dapat melihat teks biasa berikut:

MyPlainTextResponse

Siyavash Hamdi
sumber
Jangan buang namespace string dengan hal-hal yang tidak terkait dengan string.
Rambalac