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

回答:


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%に返すため、これが実際に解決策でした直接応答で発生したため、問題はありませんでした。2つまたは3つのメソッドでのみ.NET文字列を返し、JSON文字列として返されていました。あなたの答えは、私見ですが、この問題に対するKISS応答です(100%DRYではありませんが、それを行うための文字列への拡張メソッドを記述しただけです... :-)いいですね!)StringContentはとてもいいです。ありがとうございました。
Loudenvier 2013年

この種のことを非常に簡単にする特定のタイプのコンテンツを作成するためのカスタムXXXContentクラスがいくつかあります。
Rick Strahl、

私はこのアプローチで正しい応答を見る。ただし、現在HttpContext.Currentはnullです。これに関するアイデアはありますか?
Nachiket Mehta、2015

@JavascriptEnthusiast-ほとんどの場合、HttpContext.Currentはnullです。これは、セルフホスティングを行っているか、System.WebパイプラインなしでOWinスタックを実行しているためです。このソリューションとは無関係です。
Rick Strahl、2015

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

グローバル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には1つあります。
  • プレーンテキストフォーマッタを登録している場合は、コントローラでコンテンツタイプヘッダーをオンhttpResponseMessage.Headersに設定することで強制できtext/plainます。

心配する必要はありません。HttpContextオブジェクトを暗黙に使用するつもりはありません。従来のASP.NETでどのように使用するかを示すために追加しただけです
Magnus Johansson

ええと、waddayknow、私はすでにWebAPIContribを参照していましたが、簡単な場合もあります。
マグナスヨハンソン、

@マグナス確かに。実際、自分が書いたものを読んだ後、表現を変えました。しかし、別の答えを読んで、私はその最初のポイントを強調しました。
Aliostad 2012

あなたはHttpContext.Currentを使用しないと言っていますが、代替手段は何ですか?
スーリヤ2013

@spiderdevilはい、それは絶対に私が言っていることです。必要ありません。リクエスト/レスポンス/設定を直接渡します。
Aliostad 2013


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


文字列に関係のないもので文字列の名前空間を無駄にしないでください。
Rambalac
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.