10 Stimmen

WCF Rest Webservice mit Stream

Ich habe den folgenden Beitrag mit Interesse gelesen, da er genau dem Problem entspricht, das ich habe (und das mich in den Wahnsinn treibt) "Damit die Anforderung in der Operation UploadFile ein Stream ist, muss die Operation einen einzelnen Parameter haben, dessen Typ Stream ist." - http://social.msdn.microsoft.com/Forums/en/wcf/thread/80cd26eb-b7a6-4db6-9e6e-ba65b3095267

Ich habe so ziemlich alle Codes/Beispiele befolgt, die ich gefunden habe, und kann diesen Fehler trotzdem nicht umgehen. http://blogs.msdn.com/b/carlosfigueira/archive/2008/04/17/wcf-raw-programming-model-receiving-arbitrary-data.aspx

Alles, was ich erreichen möchte, ist ein Bild (jpeg/png) von einem Android-Gerät unter Verwendung der Standard-Dateinamen/Stream-Parameter zu posten Höchstwahrscheinlich ist es etwas Einfaches, das ich falsch konfiguriert, missverstanden oder ausgelassen habe, aber ich muss eine Lösung für den Nachweis des Konzepts haben.

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

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

Ich verwende vs2010 und IIS Express. Wenn ich die obige Methode auskommentiere, funktionieren alle anderen Methoden und geben Daten zurück, ebenso wie die WSDL-Abfrage

Mit freundlichen Grüßen und Dank im Voraus Kern

16voto

Drew Marsh Punkte 32833

Sie erwähnen WSDL, was mich zu der Annahme führt, dass Sie den Fehler erhalten, wenn Sie versuchen, den Metadaten-Endpunkt für den Dienst zu durchsuchen. Zunächst einmal passen WSDL und REST nicht zusammen, also sollten Sie nicht erwarten, dass Sie es überhaupt für eine REST-Schnittstelle verwenden können. Vergessen Sie, dass das Konzept der Dienstmetadaten in der REST-Welt überhaupt existiert.

Next Es stimmt zwar, dass die webHttpBinding von REST Parameter vor dem Stream-Body-Parameter unterstützt, aber andere Bindungen tun dies nicht und es muss entweder ein einzelner Stream-Parameter oder ein Nachrichtenvertrag mit Headern und einem Stream-Body vorhanden sein.

Also, am Ende, das Problem ist nicht mit der REST webHttpBinding überhaupt, ich wette, es funktioniert ganz gut. Wenn nicht, wäre ich absolut schockiert, denn Sie tun nichts, was nicht in dieser Abteilung funktionieren sollte. Das Problem ist, dass Sie erwarten, dass der Metadaten-Endpunkt WSDL für den von Ihnen definierten Dienstvertrag generiert, und das wird einfach nicht unterstützt.

0voto

jst Punkte 1

Ich mache es auf diese Weise und es funktioniert.

Fabrikklasse zum Webservice hinzufügen (WcfService2.ServiceFactory)

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

Meine Schnittstelle:

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

 }

Meine Methode:

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

Ich habe eine EndpointBehaviors-Klasse hinzugefügt, die die Operation UploadFile findet und deren DataContractSerializerOperationBehavior entfernt, und funktioniert dann!

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X