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