Может ли атрибут WebGet метода WCF OperationContract иметь несколько типов ResponseFormat? - PullRequest
17 голосов
/ 17 ноября 2009

У меня есть ServiceContract, описывающий метод, используемый в службе WCF. У метода есть атрибут WebGet, который определяет UriTemplate и ResponseFormat.

Я хочу повторно использовать один метод и иметь несколько атрибутов WebGet с разными UriTemplates и разными ResponseFormats. По сути, я надеюсь избежать использования нескольких методов просто для того, чтобы различать такие вещи, как тип возвращаемого значения - XML ​​и JSON. Во всех примерах, которые я видел до сих пор, я должен создавать разные методы для каждого атрибута WebGet. Вот пример OperationContract

[ServiceContract]
public interface ICatalogService
{
    [OperationContract]
    [WebGet(UriTemplate = "product/{id}/details?format=xml", ResponseFormat = WebMessageFormat.Xml)]
    Product GetProduct(string id);

    [OperationContract]
    [WebGet(UriTemplate = "product/{id}/details?format=json", ResponseFormat = WebMessageFormat.Json)]
    Product GetJsonProduct(string id);
}

Используя приведенный выше пример, я бы хотел использовать метод GetProduct для обоих типов возвращаемых данных xml и json:

[ServiceContract]
public interface ICatalogService
{
    [OperationContract]
    [WebGet(UriTemplate = "product/{id}/details?format=xml", ResponseFormat = WebMessageFormat.Xml)]
    [WebGet(UriTemplate = "product/{id}/details?format=json", ResponseFormat = WebMessageFormat.Json)]
    Product GetProduct(string id);
}

Есть ли способ достичь этого, поэтому я не застрял в написании разных методов только для того, чтобы вернуть разные ResponseFormats?

Спасибо!

Ответы [ 2 ]

12 голосов
/ 04 ноября 2010

Вы можете сделать это

[ServiceContract]
public interface ICatalogService
{
    [OperationContract]
    [WebGet(UriTemplate = "product/{id}/details?format={format}")]
    Stream GetProduct(string id, string format);
}

И затем в вашем коде обрабатывается сериализация на основе значения, указанного в параметре.

Для XML напишите вспомогательный метод, который обрабатывает вашу сериализацию.

public static Stream GetServiceStream(string format, string callback, DataTable dt, SyndicationFeed sf)
        {
            MemoryStream stream = new MemoryStream();
            StreamWriter writer = new StreamWriter(stream, Encoding.UTF8);
            if (format == "xml")
            {
                XmlSerializer xmls = new XmlSerializer(typeof(DataTable));
                xmls.Serialize(writer, dt);
                WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
            }
            else if (format == "json")
            {
                var toJSON = new JavaScriptSerializer();
                toJSON.RegisterConverters(new JavaScriptConverter[] { new JavaScriptDataTableConverter() });
                writer.Write(toJSON.Serialize(dt));
                WebOperationContext.Current.OutgoingResponse.ContentType = "text/json";
            }
            else if (format == "jsonp")
            {
                var toJSON = new JavaScriptSerializer();
                toJSON.RegisterConverters(new JavaScriptConverter[] { new JavaScriptDataTableConverter() });
                writer.Write(callback + "( " + toJSON.Serialize(dt) + " );");
                WebOperationContext.Current.OutgoingResponse.ContentType = "text/json";
            }
            else if (format == "rss")
            {
                XmlWriter xmlw = new XmlTextWriter(writer);
                sf.SaveAsRss20(xmlw);
                WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
            }
            else if (format == "atom")
            {
                XmlWriter xmlw = new XmlTextWriter(writer);
                sf.SaveAsAtom10(xmlw);
                WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
            }
            else
            {
                writer.Write("Invalid formatting specified.");
                WebOperationContext.Current.OutgoingResponse.ContentType = "text/html";
            }

            writer.Flush();
            stream.Position = 0;
            return stream;
        }
}
8 голосов
/ 07 марта 2011

Если я правильно помню, у меня работал метод ниже:

Договор на обслуживание json:

[ServiceContract]
public interface IServiceJson {
  [OperationContract()]
  [WebGet(UriTemplate = "Operation/?param={param}",
                         ResponseFormat = WebMessageFormat.Json)]
  ReturnType Operation(string param);
}

Контакт для службы xml:

[ServiceContract]
public interface IServiceXml {
  [OperationContract(Name = "OperationX")]
  [WebGet(UriTemplate = "Operation/?param={param}",
                         ResponseFormat = WebMessageFormat.Xml)]
  ReturnType Operation(string param);
}

Реализация для обоих:

public class ServiceImplementation : IServiceJson, IServiceXml {
  ReturnType Operation(string param) {
    // Implementation
  }
}

И конфигурация web.config (обратите внимание на конечные точки для ответов json и xml):

  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="webHttp">
          <webHttp />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="serviceBehaviour">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="serviceBehaviour" name="ServiceImplementation">
        <endpoint address="json/" behaviorConfiguration="webHttp" binding="webHttpBinding"
         bindingConfiguration="webHttpBindingSettings" contract="IServiceJson">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="xml/" behaviorConfiguration="webHttp" binding="webHttpBinding"
         bindingConfiguration="webHttpBindingSettings" contract="IServiceXml">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <bindings>
      <webHttpBinding>
        <binding name="webHttpBindingSettings">
          <readerQuotas maxStringContentLength="5000000"/>
        </binding>
      </webHttpBinding>
    </bindings>
  </system.serviceModel>

Теперь вы можете позвонить в вашу службу следующим образом: json response: http://yourServer/json/Operation/?param=value xml ответ: http://yourServer/xml/Operation/?param=value

(Извините, если в приведенном выше коде есть ошибки, я не запустил его для проверки).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...