Заставить веб-сервис ASP.net вернуть JSON - PullRequest
20 голосов
/ 09 сентября 2009

У меня есть веб-служба ASP.net, которую я использую для веб-приложения, которое возвращает мне данные в формате XML или JSON, в зависимости от вызываемой функции. До сих пор это работало хорошо, но я столкнулся с проблемой. Я хочу создать ссылку "экспорт" на своей странице, которая будет загружать файл 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, я всегда получаю XML обратно, если не запрашиваю этот метод через AJAX (используя Google Web Toolkit, BTW):

    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 будет практически бесполезен для этой функции). Возврат чего-либо испортит ответ, который создается вручную.

Ответы [ 3 ]

11 голосов
/ 09 сентября 2009

Веб-сервисы Asp.net являются веб-сервисами на основе SOAP. Они всегда будут возвращать XML. Появились библиотеки Ajax и был представлен материал ScriptMethod, но он не меняет основную концепцию этого.

Есть пара вещей, которые вы можете сделать.

WebMethods устарели с введением WCF. Вы можете перенести свои веб-сервисы на WCF , в котором у вас будет гораздо больший контроль над форматом вывода.

Если вы не хотите этого делать, вы можете вручную сериализовать результат ваших вызовов веб-службы в JSON, и служба поместит его в заголовок SOAP. Затем вам нужно будет удалить содержимое SOAP.

2 голосов
/ 09 сентября 2009

Вот две темы форума для вашей справки:

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

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

Понятия не имею. Они говорят о том, чтобы сконцентрироваться на установке типа контента на application / json. Я не работал с wcf раньше, но я думаю, что вы можете использовать объект Response.

Установить тип содержимого для объекта ответа. Сделайте response.write, передавая ваши данные json в виде строки, а затем выполните response.end.

1 голос
/ 10 сентября 2009

Просто подумал, что я добавлю это, поскольку это не упоминалось ранее ... если вы используете WebServices с ASP.NET 3.5, JSON является форматом возврата по умолчанию. Он также поставляется с сериализатором JSON, поэтому вы можете прекратить использование JavascriptSerializer.

В этой статье в блоге Рика Строла рассказывается о строго типизированном преобразовании, которое вы можете выполнять между классами на стороне сервера и объектами JSON из клиента.

Я недавно завершил проект с использованием этого нового материала JSON в .NET 3.5, и я чрезвычайно впечатлен производительностью. Может быть, стоит посмотреть ...

...