带流的 WCF Rest Web 服务

发布于 2024-11-15 13:31:37 字数 2197 浏览 0 评论 0原文

我饶有兴趣地阅读了以下帖子,因为它是我所遇到的问题的精确复制品(并且让我发疯) “为了使 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- Arbitration-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 查询

提前致以问候和感谢 克恩

I read the following post with interest as it is an exact replica of the problem I am experiencing (and driving me insane)
"For request in operation UploadFile to be a stream the operation must have a single parameter whose type is Stream." -http://social.msdn.microsoft.com/Forums/en/wcf/thread/80cd26eb-b7a6-4db6-9e6e-ba65b3095267

I have pretty much followed all code/examples I have found and yet still cannot get around this error -
http://blogs.msdn.com/b/carlosfigueira/archive/2008/04/17/wcf-raw-programming-model-receiving-arbitrary-data.aspx

All I would like to achieve is to post an image(jpeg/png) from an android device using the standard filename/stream parameters.More than likely it is something simple that I have misconfigured, misunderstood or left out but I need to have a solution for proof of concept.

 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 settings

-->

<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>

Using vs2010 and IIS Express. If I comment out the above method all the others methods work and return data as well as the wsdl query

Regards and thanks in advance
Kern

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

空心↖ 2024-11-22 13:31:37

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

虽然 REST 的 webHttpBinding 确实支持 Stream body 参数前面的参数,但其他绑定不支持,并且必须有单个 Stream 参数或带有标头和流正文的消息协定。

所以,最后,问题根本不在于 REST webHttpBinding,我敢打赌它工作得很好。如果不是这样,我会感到绝对震惊,因为你没有做任何不应该在该部门工作的事情。问题是您期望元数据端点为您定义的服务契约生成 WSDL,但这不受支持。

You mention WSDL, which leads me to believe you're getting the error while trying to browse the metadata endpoint for the service. So, first off, WSDL and REST don't go together, so you shouldn't expect to use it at all for a REST interface. Forget the service metadata concept even exists in the REST world.

Next While it's true the REST's webHttpBinding supports parameters in front of the Stream body parameter, other bindings do not and there must either be a single Stream parameter or a message contract with headers and a stream body.

So, in the end, the problem is not with the REST webHttpBinding at all, I bet it works just fine. If it doesn't I would be absolutely shocked because you're not doing anything that shouldn't work in that department. The problem is that you're expecting the metadata endpoint to generate WSDL for the service contract you've defined and that's just not supported.

旧时光的容颜 2024-11-22 13:31:37

我就是这样做的并且有效。

将工厂类添加到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类,它找到操作UploadFile并删除其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).");
            }           
        }
    }

I do it this way and it'works.

Add Factory Class to webservice (WcfService2.ServiceFactory)

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

My Interface:

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);


 }

My Method:

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

        }

my 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();
            }
        }
    }

I added a EndpointBehaviors class, wich it find de operation UploadFile and remove its DataContractSerializerOperationBehavior, and then works!

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).");
            }           
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文