WCF Rest Web Service with stream

时间:2011-06-16 02:26:19

标签: wcf rest stream

我感兴趣地阅读了以下帖子,因为它是我遇到的问题的精确复制品(并让我疯狂) “对于操作中的请求,UploadFile是一个流,操作必须有一个类型为Stream的参数。” - http://social.msdn.microsoft.com/Forums/en/wcf/thread/80cd26eb-b7a6-4db6-9e6e-ba65b3095267

我几乎遵循了我找到的所有代码/示例,但仍然无法解决此错误 - http://blogs.msdn.com/b/carlosfigueira/archive/2008/04/17/wcf-raw-programming-model-receiving-arbitrary-data.aspx

我想要实现的是使用标准文件名/流参数从Android设备发布图像(jpeg / png)。很可能这是一个简单的东西我错误配置,误解或遗漏但我需要有一个概念证明的解决方案。

 public interface IConXServer
    {
    [OperationContract]
    [WebInvoke(UriTemplate = "UploadImage({fileName})", Method="POST")]
    void UploadImage(string fileName, Stream imageStream);
    }

 public class ConXWCFServer : IConXServer
    {
    public void UploadImage(string fileName, Stream imageStream)
       {
       //implement image save
       }
    }

web.config设置                         - >                                   

<standardEndpoints>
   <webHttpEndpoint>
       <standardEndpoint name="webHttpEndpoint" helpEnabled="false"/>
   </webHttpEndpoint>
</standardEndpoints>

<bindings>
    <webHttpBinding>
        <binding name="webHttpBinding" transferMode="Streamed"/>
    </webHttpBinding>
</bindings>

<behaviors>
    <endpointBehaviors>
        <behavior name="webHttpBehavior">
            <webHttp/>
        </behavior>
    </endpointBehaviors> 
    <serviceBehaviors>
        <behavior>
            <serviceMetadata httpGetEnabled="false"/>
            <serviceDebug includeExceptionDetailInFaults="true"/>
            <serviceThrottling maxConcurrentCalls="2147483647"  maxConcurrentSessions="2147483647"/>
        </behavior>
    </serviceBehaviors>
</behaviors>

使用vs2010和IIS Express。如果我注释掉上述方法,则所有其他方法都可以工作并返回数据以及wsdl查询

提前问候并表示感谢 克恩

2 个答案:

答案 0 :(得分:13)

您提到WSDL,这让我相信您在尝试浏览服务的元数据端点时会收到错误。因此,首先,WSDL和REST不会一起使用,因此您不应期望将它用于REST接口。忘记服务元数据概念甚至存在于REST世界中。

Next虽然REST的webHttpBinding支持Stream body参数前面的参数,但其他绑定不支持,并且必须有一个Stream参数或带有标题和流体的消息合约。

所以,最后,问题不在于REST webHttpBinding,我打赌它的工作正常。如果不是,我会非常震惊,因为你没有做任何不应该在该部门工作的事情。问题是您希望元数据端点为您定义的服务合同生成WSDL,而且不支持。

答案 1 :(得分:0)

我这样做是可行的。

将工厂类添加到Web服务(WcfService2.ServiceFactory)

<%@ ServiceHost Language="C#" Debug="true" Service="WcfService2.Service1" CodeBehind="Service1.svc.cs" Factory="WcfService2.ServiceFactory" %>

我的界面:

public interface IService1

 {

[OperationContract]
        [WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest, Method = "POST",
         RequestFormat = WebMessageFormat.Json,
            ResponseFormat = WebMessageFormat.Json,
            UriTemplate = "UploadFile/{fileName}")]

        void UploadFile(string fileName, Stream fileContent);


 }

我的方法:

public void UploadFile(string fileName, Stream fileContent)
        {

            var pathfile = "\\\\SERVER\\TravelsRequestFiles";
            using (var fileStream = new FileStream(string.Concat(pathfile, "\\", fileName), FileMode.Create, FileAccess.Write))
            {
                fileContent.CopyTo(fileStream);
            }

        }

我的FactoryClass:

public class ServiceFactory : ServiceHostFactory

    {
        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)

        {
            return new MyServiceHost(serviceType, baseAddresses);
        }

        class MyServiceHost : ServiceHost

        {
            public MyServiceHost(Type serviceType, Uri[] baseAddresses)
              : base(serviceType, baseAddresses)
            {
            }

            protected override void InitializeRuntime()
            {
                ServiceEndpoint endpoint = this.Description.Endpoints[0];
                endpoint.Behaviors.Add(new EndpointBehaviors());

                base.InitializeRuntime();
            }
        }
    }

我添加了一个EndpointBehaviors类,通过它找到deleteFile操作并删除其DataContractSerializerOperationBehavior,然后开始工作!

public class EndpointBehaviors: IEndpointBehavior

    {

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {

            ContractDescription cd = endpoint.Contract;
            foreach (DispatchOperation objDispatchOperation in endpointDispatcher.DispatchRuntime.Operations)
            {
                if (objDispatchOperation.Name.Equals("UploadFile"))
                {
                    OperationDescription myOperationDescription = cd.Operations.Find("UploadFile");

                    DataContractSerializerOperationBehavior serializerBehavior = myOperationDescription.Behaviors.Find<DataContractSerializerOperationBehavior>();
                    myOperationDescription.Behaviors.Remove(serializerBehavior);                
                }
            }
        }
        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
        }
        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }

        public void Validate(ServiceEndpoint endpoint)
        {
            BindingElementCollection elements = endpoint.Binding.CreateBindingElements();
            WebMessageEncodingBindingElement webEncoder = elements.Find<WebMessageEncodingBindingElement>();
            if (webEncoder == null)
            {
                throw new InvalidOperationException("This behavior must be used in an endpoint with the WebHttpBinding (or a custom binding with the WebMessageEncodingBindingElement).");
            }           
        }
    }