如何将文件上传到IIS中托管的.net 3.5 WCF服务

本文关键字:net 服务 WCF 文件 IIS | 更新日期: 2023-09-27 18:04:38

我已经抓狂一阵子了。有人能提供一个非常简单的例子(或一个链接到一个工作的例子)如何上传一个文件到托管在IIS中的WCF服务。

我从一些简单的开始。我想通过POST从客户端调用URL,传递文件的名称并发送文件。因此,我在合同中添加了以下内容:

[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/UploadFile?fileName={fileName}")]
void Upload(string fileName, Stream stream);

在.svc文件中实现:

public void Upload(string fileName, Stream stream)
{
    Debug.WriteLine((fileName));
}

立即,我得到一个错误在运行项目:

For request in operation Upload to be a stream the operation must have a single parameter whose type is Stream.

不知道从这里去哪里。希望能看到一个实际的工作示例。

注:我在。net 4中使用了WCF 4,它看起来简单多了,但我不得不降级。在。net 3.5中,我缺少了一些东西。

如何将文件上传到IIS中托管的.net 3.5 WCF服务

为了使其工作,您需要定义一个与WebHttpBinding兼容的绑定端点,并将WebHttpBehavior添加到其中。这条消息可能是转移注意力,这是一个老bug,如果你浏览到服务基地地址,如果你启用了元数据,它就会显示出来。另一个问题是,如果你想能够上传任何文件类型(包括JSON和XML),你需要定义一个WebContentTypeMapper来告诉WCF不要试图理解你的文件(更多信息见http://blogs.msdn.com/b/carlosfigueira/archive/2008/04/17/wcf-raw-programming-model-receiving-arbitrary-data.aspx)。

这是一个完整的例子。3.5最大的问题是ContentTypeMapper属性在WebHttpBinding上不存在,所以你需要使用自定义绑定。这段代码使用自定义ServiceHostFactory定义端点,但是也可以使用config定义端点。

Service.svc

<%@ ServiceHost Language="C#" Debug="true" Service="MyNamespace.MyService" Factory="MyNamespace.MyFactory" %>

Service.cs

using System;
using System.Diagnostics;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Web;
public class MyNamespace
{
    [ServiceContract]
    public interface IUploader
    {
        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "/UploadFile?fileName={fileName}")]
        void Upload(string fileName, Stream stream);
    }
    public class Service : IUploader
    {
        public void Upload(string fileName, Stream stream)
        {
            Debug.WriteLine(fileName);
        }
    }
    public class MyFactory : ServiceHostFactory
    {
        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            return new MyServiceHost(serviceType, baseAddresses);
        }
        class MyRawMapper : WebContentTypeMapper
        {
            public override WebContentFormat GetMessageFormatForContentType(string contentType)
            {
                return WebContentFormat.Raw;
            }
        }
        public class MyServiceHost : ServiceHost
        {
            public MyServiceHost(Type serviceType, Uri[] baseAddresses)
                : base(serviceType, baseAddresses) { }
            protected override void OnOpening()
            {
                base.OnOpening();
                CustomBinding binding = new CustomBinding(new WebHttpBinding());
                binding.Elements.Find<WebMessageEncodingBindingElement>().ContentTypeMapper = new MyRawMapper();
                ServiceEndpoint endpoint = this.AddServiceEndpoint(typeof(IUploader), binding, "");
                endpoint.Behaviors.Add(new WebHttpBehavior());
            }
        }
    }
}