Подтвердить что ты не робот

Может ли метод WCF OperationContract атрибут WebGet иметь несколько типов ResponseFormat?

У меня есть 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?

Спасибо!

4b9b3361

Ответ 1

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

[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;
        }
}

Ответ 2

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

Контракт на обслуживание 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 response: http://yourServer/xml/Operation/?param=value

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