Servicios .NET WCF RIA +; ¿Puedo tenerlo todo?

What I'd like to have is "regular" WCF service calls responding on my root URL as well as the regular RIA stuff. Seems simple, but is turning out to be a bit of a pain. The RIA stuff works including ODATA JSON and SOAP, but the traditional web services doesn't want to run off the root URL.

Ver el siguiente código:

using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server;
using System.ServiceModel.Web;
using Microsoft.ServiceModel.DomainServices.Hosting;

namespace ConsoleApplication1
{
    public partial class Program
    {
        [EnableClientAccess, ServiceContract]
        public class TestDomainService : DomainService
        {
            [Query(IsDefault = true)]
            public IQueryable<Foo> GetAllFoos()
            {
                return new Foo[] { new Foo { Id = 1, Name = "Jonathan" } }.AsQueryable();
            }

            [WebInvoke(Method="GET"), OperationContract]
            public Message Test()
            {
                return WebOperationContext.Current.CreateTextResponse("Test");
            }
        }

        public class Foo
        {
            [Key]
            public int Id { get; set; }
            public string Name { get; set; }
        }

        static void Main(string[] args)
        {
            var baseUri = new Uri("http://localhost:999");

            var svc = new DomainServiceHost(typeof(TestDomainService), new Uri[] { baseUri });
            svc.Description.Behaviors.RemoveAll<AspNetCompatibilityRequirementsAttribute>();
            svc.Description.Behaviors.OfType<ServiceMetadataBehavior>().First().HttpGetEnabled = true;

            var svcDescription = DomainServiceDescription.GetDescription(typeof(TestDomainService));
            var odataEndpoints = new ODataEndpointFactory().CreateEndpoints(svcDescription, svc);
            var soapEndpoints = new SoapXmlEndpointFactory().CreateEndpoints(svcDescription, svc);
            var jsonEndpoints = new JsonEndpointFactory().CreateEndpoints(svcDescription, svc);

            var odata = odataEndpoints.First();
            odata.Contract.Namespace = new Uri(baseUri, "ODATA").ToString();
            odata.Address = new System.ServiceModel.EndpointAddress(new Uri(baseUri, "ODATA"));

            var soap = soapEndpoints.First();
            soap.Contract.Namespace = new Uri(baseUri, "SOAP").ToString();
            soap.Address = new System.ServiceModel.EndpointAddress(new Uri(baseUri, "SOAP"));

            var json = jsonEndpoints.First();
            json.Contract.Namespace = new Uri(baseUri, "JSON").ToString();
            json.Address = new System.ServiceModel.EndpointAddress(new Uri(baseUri, "JSON"));

            var ep = new ServiceEndpoint(svc.Description.Endpoints[0].Contract, new WebHttpBinding(), new EndpointAddress(baseUri));
            ep.Behaviors.Add(new WebHttpBehavior());
            var cd = ContractDescription.GetContract(typeof(TestDomainService));
            foreach (var op in cd.Operations)
            {
                if (ep.Contract.Operations.Any(o => o.Name == op.Name) == false)
                {
                    ep.Contract.Operations.Add(op);
                }
            }
            svc.Description.Endpoints.Add(ep);

            svc.Description.Endpoints.Add(odata);
            svc.Description.Endpoints.Add(soap);
            svc.Description.Endpoints.Add(json);

            svc.Open();

            foreach (var endpoint in svc.Description.Endpoints)
            {
                Console.WriteLine("Domain service started on: {0}", endpoint.Address.Uri);
            }

            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
}

Accediendo http://localhost:999/Test should result in just Test being displayed, but instead I get:

<Fault xmlns="http://schemas.microsoft.com/ws/2005/05/envelope/none">
    <Code>
        <Value>Sender</Value>
        <Subcode>
            <Value xmlns:a="http://schemas.microsoft.com/ws/2005/05/addressing/none">a:ActionNotSupported</Value>
        </Subcode>
    </Code>
    <Reason>
        <Text xml:lang="en-US">The message with Action '' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).</Text>
    </Reason>
</Fault>

¿Alguien puede ver lo que me estoy perdiendo?

Gracias de antemano!

preguntado el 09 de noviembre de 11 a las 16:11

1 Respuestas

For me, I just needed to return raw strings on that endpoint so I implemented my own HttpBehavior and DispatchFormatter as such:

    public class WebHttpBehaviorEx : WebHttpBehavior
    {
        protected override IDispatchMessageFormatter GetReplyDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)
        {
            return new DynamicFormatter();
        }
    }

    public class DynamicFormatter : IDispatchMessageFormatter
    {
        public void DeserializeRequest(Message message, object[] parameters)
        {
            throw new NotImplementedException();
        }

        public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
        {
            return WebOperationContext.Current.CreateTextResponse((result ?? string.Empty).ToString());
        }
    }

y cambiado

ep.Behaviors.Add(new WebHttpBehavior());

respondido 10 nov., 11:18

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.