Question

I have a service contract as follows:

[ServiceContract]
public interface IWebProxyService
{
    [OperationContract]
    string GetSomeData();
}

I have also tried this attribute on the contract.

[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "/GetFormsBaseUrl")] 

Is it possible to call this from another application without any service references/contracts.

I have tried the a bunch of variations of the following (from calling app):

 public static void GetSomeData(string webServiceProxyURL)
    {
        WebRequest request = WebRequest.Create(webServiceProxyURL);
        request.Method = "GET";
        request.ContentType = "application/json";
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        Stream dataStream = response.GetResponseStream();
        StreamReader reader = new StreamReader(dataStream);
        string responseFromServer = reader.ReadToEnd();
        Console.WriteLine("Response: \n" + responseFromServer);

    }

I get a "The remote server returned an error: (400) Bad Request". The web exception status is "System.Net.WebExceptionStatus.ProtocolError" What am I doing wrong, how can I call the WCF method from the other app?

Était-ce utile?

La solution

You won't to be able to do it like in your code and get a response like that. The 'bad request' is just WCF telling you that your request does not conform to what WCF expects. All WCF calls expects the message to be in SOAP format, otherwise the server won't be able to recognize your call. Imagine, if your service contract has two methods instead of just once, how does WCF know which one to call when you send a request like that? The answer is, when you call WCF using the client proxy (either generated by tool or created by yourself using ChannelFactory), the request is encapsulated into a SOAP message which contains a lot more information to allow WCF to identify which endpoint you want to call, what method to call, and what parameters you supplied.

If you do want to avoid using client side proxy class (you didn't say the reason, so I assume you have a good one), you can, theoretically, construct SOAP message by yourself, and embedded into the http header and send with the http web request. However, this is apparently not an approach I'd recommend.

Now, if you have power over the service contract, you can consider implementing RESTful api in your web service, and it will allow you to access the service using normal http url like "http://yourserver.com/getdata". And implementing RESTful service is quite easy in WCF for most cases, you merely need to add a attribute to your service contract! Change it to something like this (adding an attribute, nothing else)

[ServiceContract]
public interface IWebProxyService
{
    [OperationContract]
    [WebGet(UriTemplate="getData")]
    string GetSomeData();
}

And then configure your service to use webHttpBinding, like below:

<configuration>
   <system.serviceModel>
     <services>
        <service name="...">
            <endpoint binding="webHttpBinding" contract="..."
                      behaviorConfiguration="webHttp"/>
        </service>
     </services>
     <behaviors>
        <endpointBehaviors>
            <behavior name="webHttp">
                <webHttp/>
            </behavior>
        </endpointBehaviors>
     </behaviors>
  </system.serviceModel>
<configuration>

Then from the client side, you can access the web service without using service contract, just normal WebRequest; You need to append a '/getData' to the end of your service uri, and the response is in xml format.

RESTful api can allow you do more things (like supplying parameters, or modify data etc.) all using simple url. For a tutorial on WCF RESTful api, see this. Or search MSDN.

Edit: you don't even need to write code to verify the restful api works, you can just launch your web browser and see the response from the server, which is great for testing.

Autres conseils

The following is not an answer, just a fat comment. I hope it stays around long enough for the OP to read it.

One big problem with your code is that you're not handing IDisposable objects properly. This will cause resource leaks. Try the following:

public static void GetSomeData(string webServiceProxyURL)
{
    var request = WebRequest.Create(webServiceProxyURL);
    request.Method = "GET";
    request.ContentType = "application/json";
    string responseFromServer = "No response from server";
    using (var response = (HttpWebResponse) request.GetResponse())
    {
        using (var dataStream = response.GetResponseStream())
        {
            if (dataStream != null)
            {
                using (var reader = new StreamReader(dataStream))
                {
                    responseFromServer = reader.ReadToEnd();
                }
            }
        }
    }
    Console.WriteLine("Response: \n" + responseFromServer);
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top