ASP.NET Web API'yi düz metin döndürmeye zorlamanın bir yolu var mı?


125

Bir ASP.NET Web API denetleyicisinden düz metin olarak yanıt almam gerekiyor.

İle bir istek yapmayı denedim Accept: text/plainama hile yapmıyor gibi görünüyor. Üstelik bu istek dışarıdan ve benim kontrolüm dışında. Yapacağım şey eski ASP.NET yöntemini taklit etmektir:

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

Herhangi bir fikir?

EDIT, çözüm : Aliostad'ın cevabına dayanarak, WebAPIContrib metin biçimlendiricisini ekledim, Application_Start'ta başlattım:

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

ve denetleyicim şöyle bir şeyle sonuçlandı:

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

Yanıtlar:


231

Hmmm ... Bunun çalışması için özel bir formatlayıcı oluşturmanız gerektiğini düşünmüyorum. Bunun yerine içeriği şu şekilde döndür:

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

Bu benim için özel bir biçimlendirici kullanmadan çalışıyor.

Açıkça çıktı oluşturmak ve Kabul başlıklarına dayalı olarak varsayılan içerik anlaşmasını geçersiz kılmak istiyorsanız Request.CreateResponse(), mime türünü zorladığından kullanmak istemeyeceksiniz .

Bunun yerine, açıkça yeni bir tane oluşturun HttpResponseMessageve içeriği manuel olarak atayın. Yukarıdaki örnek kullanır, StringContentancak çeşitli .NET veri türlerinden / yapılarından veri döndürmek için kullanılabilen epeyce başka içerik sınıfı vardır.


1
Aslında bu benim aradığım çözüm çünkü API'm JSON nesnelerini tüm yöntemlerin% 99'una döndürüyordu, yalnızca birkaç (çok az) yöntem düz dize yanıtlarına ihtiyaç duyacaktı (ve bunların çoğu için veri döndürmek için bir MemoryStream kullanıyorum doğrudan yanıttaydı, bu nedenle sorun değildi.) Yalnızca 2 veya 3 yöntemde bir .NET dizesi döndürdüm ve bir JSON dizesi olarak döndürülüyordu. Cevabınız, IMHO, bu problem için KISS cevabıdır (her ne kadar% 100 DRY olmasa da, bunu yapmak için dizeye bir uzatma yöntemi yazdım ... :-) Güzel!) StringContent çok güzel. Teşekkür ederim.
Loudenvier

Bu tür şeyleri oldukça basit hale getiren belirli içerik türleri oluşturmak için bir dizi özel XXXContent sınıfı vardır.
Rick Strahl

Bu yaklaşımla doğru yanıtı görüyorum. Ancak, HttpContext.Current artık null. Bununla ilgili herhangi bir fikrin var mı?
Nachiket Mehta

@JavascriptEnthusiast - HttpContext.Current, büyük olasılıkla boştur çünkü System.Web ardışık düzeni olmadan kendi kendine barındırma veya OWin yığını üzerinden çalıştırma. Yine de bu çözümle alakasız.
Rick Strahl

15

Ek bağımlılıklar eklemeden sadece basit bir düz / metin biçimlendiricisi arıyorsanız, bu hile yapmalıdır.

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 yapılandırmanıza eklemeyi unutmayın.

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

Artık dize nesnelerini

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


12
  • Lütfen ASP.NET Web API'sinde bağlam kullanmamaya dikkat edin, aksi takdirde er ya da geç özür dileyeceksiniz. ASP.NET Web API'sinin zaman uyumsuz doğası HttpContext.Currentbir sorumluluk kullanmayı sağlar .
  • Bir düz metin biçimlendiricisi kullanın ve biçimlendiricilerinize ekleyin. Etrafta düzinelerce var. Seninkini bile kolayca yazabilirsin. WebApiContrib bir tane var.
  • Üzerinde içerik türü başlığını ayarlayarak zorlayabilirsiniz httpResponseMessage.Headersiçin text/plaincontroller içerisinde düz metin biçimlendirici kayıtlı olmaları kaydıyla.

Endişelenmeyin, HttpContext nesnesini ne ima ettim ne de kullanmak niyetindeydim, bunu klasik ASP.NET'te nasıl yapılacağını göstermek için ekledim
Magnus Johansson

Eh, waddayknow, zaten WebAPIContrib'e başvurdum, bazen basit.
Magnus Johansson

@Magnus Tabii. Aslında yazdıklarımı okuduktan sonra ifadeleri değiştirdim. Ama başka bir cevabı okumak beni bu ilk noktayı vurguladı.
Aliostad

HttpContext.Current kullanmamayı söylüyorsunuz, alternatifler nelerdir?
surya

@spiderdevil evet, kesinlikle söylediğim şey bu. İhtiyacınız olmamalı, istek / yanıt / yapılandırmayı doğrudan iletmelisiniz.
Aliostad

6

Kabul Et: metin / düz çalışmazsa, metin mime türleri için kayıtlı bir biçimlendirici yoktur.

Hizmet yapılandırmasından desteklenen tüm biçimlendiricilerin listesini alarak, belirtilen mime türü için biçimlendiricilerin bulunmadığından emin olabilirsiniz.

Metin mime türlerini destekleyen çok basit bir ortam türü biçimlendiricisi oluşturun.

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


Cevabınızı da kabul edebilseydim, kabul edilen cevap beni kendi formatlayıcımı yazma zahmetinden kurtardı. En az +1.
Magnus Johansson

0

Aşağıdaki gibi bir uzantı, satır sayısını azaltabilir ve kodunuzu güzelleştirebilir:

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


Artık tanımlı uzantıyı şunlarınızda kullanabilirsiniz Web API:

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


Yönlendirme {DOMAIN}/api/Home/Indexyaparak aşağıdaki düz metni görebilirsiniz:

MyPlainTextResponse


Dize ad alanını dizeyle ilgisi olmayan şeylerle harcamayın.
Rambalac
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.