Как загрузить файл в службу WCF .NET 3.5, размещенную в IIS? - PullRequest
2 голосов
/ 05 августа 2011

Я с некоторых пор рву волосы. Может ли кто-нибудь предоставить действительно простой пример (или ссылку на рабочий пример) того, как загрузить файл в службу WCF, размещенную в IIS.

Я начал с чего-то простого. Я хочу позвонить с клиента через POST, передать имя файла и отправить файл. Поэтому я добавил в контракт следующее:

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

Не уверен, куда идти отсюда. Хотелось бы увидеть настоящий рабочий пример.

P.S. Я сделал это в .NET 4 с WCF 4, и это казалось намного проще, но мне пришлось понизить версию. В .NET 3.5 мне чего-то не хватает.

1 Ответ

4 голосов
/ 05 августа 2011

Чтобы это работало, вам нужно определить конечную точку с привязкой, совместимой с WebHttpBinding, к которой добавляется WebHttpBehavior.Сообщение может представлять собой красную сельдь, это старая ошибка, которая, если вы перейдете к базовому адресу службы и если у вас включены метаданные, будет отображена.Другая проблема заключается в том, что если вы хотите иметь возможность загружать любой тип файла (включая 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());
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...