web-dev-qa-db-ja.com

ASP.netWebサービスにJSONを返すように強制する

呼び出す関数に応じて、XMLまたはJSONデータのいずれかを返すWebアプリケーションに使用しているASP.netWebサービスがあります。これはこれまでうまく機能してきましたが、問題が発生しました。 JSONファイルをダウンロードする「エクスポート」リンクをページに作成したいと思います。リンクは非常に単純にフォーマットされています。

<a href="mywebserviceaddress/ExportFunc?itemId=2">Export This Item</a>

ご想像のとおり、これでアイテム2がエクスポートされます。

問題は、受け入れられるコンテンツタイプがJSONであることを特に要求していないため、ASP.netはXML以外のものの返送を絶対に拒否することです。これは、この状況には適切ではありません。コードは基本的に次のとおりです。

    [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public Item ExportItem(int itemId)
    {
        Context.Response.AddHeader("content-disposition", "attachment; filename=export.json"); //Makes it a download

        return GetExportItem(itemId);
    }

ResponseFormatをJSONとして指定しているにもかかわらず、AJAX(Google Web Toolkit、BTWを使用)を介してこのメ​​ソッドを要求しない限り、常にXMLを返します。

    RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, "mywebserviceaddress/ExportFunc");
    builder.setHeader("Content-type","application/json; charset=utf-8");
    builder.setHeader("Accepts","application/json");
    builder.sendRequest("{\"itemId\":2}", new RequestCallback(){...});

それは素晴らしいことですが、AJAXはダウンロードダイアログを表示しません。データがどのように要求されているかに関係なく、ASP.netにJSONを返すように強制する方法はありますか?この動作を手動でオーバーライドしないことは、設計上の重大な見落としです。


クイックアンサー:

まず、wompの答えがおそらく長期的に行くためのより良い方法だと思いますが(WCFに変換)、deostrollは私が近い将来に使用する答えに私を導きました。また、これは主にダウンロードだけが必要だったために機能するようであり、すべての状況でうまく機能するとは限らないことに注意してください。いずれにせよ、私が望む結果を得るために使用することになったコードは次のとおりです。

    [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public void ExportItem(int itemId)
    {
        Item item = GetExportItem(itemId);            

        JavaScriptSerializer js = new JavaScriptSerializer();
        string str = js.Serialize(item);

        Context.Response.Clear();
        Context.Response.ContentType = "application/json";
        Context.Response.AddHeader("content-disposition", "attachment; filename=export.json");
        Context.Response.AddHeader("content-length", str.Length.ToString());
        Context.Response.Flush();
        Context.Response.Write(str);
    }

voidの戻り値の型に注意してください(これは、WDSLがこの関数ではほとんど役に立たないことを意味します)。何かを返すと、手作りの応答が台無しになります。

21
Toji

参考までに、2つのフォーラムスレッドを次に示します。

http://forums.asp.net/t/1118828.aspx

http://forums.asp.net/p/1054378/2338982.aspx#2338982

はっきりした考えはありません。彼らは、コンテンツタイプをapplication/jsonに設定することに集中すると言います。私はこれまでwcfを使用したことがありませんが、Responseオブジェクトを利用できると思います。

応答オブジェクトにコンテンツタイプを設定します。 jsonデータを文字列として渡してresponse.writeを実行してから、response.endを実行します。

2
deostroll

Asp.net Webサービスは、SOAPベースのWebサービスです。それらは常にXMLを返します。 Ajaxライブラリが登場し、ScriptMethodが導入されましたが、基本的な概念は変わりません。

できることがいくつかあります。

WebMethodsは、WCFの導入により廃止された境界線です。 WebサービスをWCFに移行する を検討することをお勧めします。この場合、出力形式をより細かく制御できます。

それを望まない場合は、Webサービス呼び出しの結果を手動でJSONにシリアル化すると、サービスはそれをSOAPヘッダーでラップします。その後、削除する必要があります。 SOAPのもの。

11
womp

以前に言及されていなかったので、これを捨てると思っただけです... ASP.NET 3.5でWebServicesを使用する場合、JSONがデフォルトの戻り形式です。また、JSONシリアライザーが付属しているため、JavascriptSerializerの使用を停止できます。

この記事 Rick Strahlのブログで、サーバー側のクラスとクライアントからのJSONオブジェクトの間で実行できる厳密に型指定された変換について説明しています。

最近、.NET 3.5でこの新しいJSONを使用してプロジェクトを完了しましたが、そのパフォーマンスには非常に感銘を受けました。多分それは一見の価値があります...

1
Cᴏʀʏ