Return image from WCF web service - c#

I have created my first WCF webservice and I am trying to return an image from it based on some passed parameters. I am getting the error:
The content type image/jpeg of the response message does not match the content type of the binding (text/xml; charset=utf-8). If using a custom encoder, be sure that the IsContentTypeSupported method is implemented properly.
What do I need to do to resolve this issue?
The web.config file of my website that is calling the service has the following config:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IRestImageService" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:59473/RestImageService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IRestImageService"
contract="RestImageService.IRestImageService" name="BasicHttpBinding_IRestImageService" />
</client>
The webservice web.config looks like this:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true"/>
The Service Contract:
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "Image/{type}/{typeid}/{imageid}/{size}/{extension}",
RequestFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped)]
Stream Image(string type, string typeid, string imageid, string size = "lrg", string extension = "jpg");
I am very new at WCF, so any help/pointers would be greatly appreciated!
Update
After implementing Tim's suggestion, I am getting a new error:
There was no endpoint listening at localhost:59473/RestImageService.svc that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
I am not sure how to configure the web service to fix this issues. Any suggestions?
This is how I'm accessing the web service:
RestImageServiceClient client = new RestImageServiceClient();
client.Image(WSC.Common.BO.User.User.ImageFolder.Buyer, "27085", "BuyerPhoto", "LRG", "jpg");
I hope to be able to set the src tag of my image to the web service url once I get it working.

basicHttpBinding is SOAP (version 1.1). To enable REST-based services, I believe (haven't done much of it myself) that you need to use the webHttpBinding.
I would try something like this. In your service's config file, make the following changes:
<protocolMapping>
<add binding="webHttpBinding" scheme="http"/>
</protocolMapping>
This should configure your default binding to be webHttpBinding for http calls.
<behaviors>
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
The above code should add a default endpoint behavior for webHttp.
Finally, in your client config file, make the following change:
<client>
<endpoint address="http://localhost:59473/RestImageService.svc"
binding="webHttpBinding"
contract="RestImageService.IRestImageService"
name="WebHttpBinding_IRestImageService" />
</client>
I can't say for certain that this will work, but I've done a lot with WCF (on the SOAP side), so I think this will at least get you pointed in the right direction.
EDIT
RestImageServiceClient is a SOAP client. To use a REST service, you need to use an HTTP API. Here's an example from [WCF REST Service with JSON]http://www.codeproject.com/Articles/327420/WCF-REST-Service-with-JSON):
WebClient client = new WebClient();
byte[] data = client.DownloadData("http://localhost:11523/Service1.svc/GetData");
Stream stream = new MemoryStream(data);
DataContractJsonSerializer obj = new DataContractJsonSerializer(typeof(string));
string result = obj.ReadObject(stream).ToString();
I recommend googling "WCF REST JSON Client exmaple" - you'll get lots of hits and a few different ways to do this.
As an added note, you could make a SOAP call with your SOAP client, as long as you have a SOAP endpoint exposed on the service.

Related

Using REST GET in WCF as 2nd endpoint

I trying to add 2nd endpoint in existing WCF Application and my REST method doesn't work.
I created new Interface
[ServiceContract]
public interface IRestService
{
[OperationContract]
[WebGet(UriTemplate = "RestURI", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
string SomeMethod();
}
And implemented it in existing service
public string SomeMethodImplementation()
{
//some logic
}
I'm trying to access this method using basicaddress/service/RestURI but getting 400 Bad Request response.
After that I added protocolMapping, 2nd endpoint and endpoint behavior to config file but it didn't help.
Right now my config file looks like this:
<system.serviceModel>
<protocolMapping>
<add scheme="http" binding="webHttpBinding"/>
</protocolMapping>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="servicename">
<endpoint address="" binding="webHttpBinding" contract="IRestService" behaviorConfiguration="web"/>
<endpoint address="" binding="basicHttpBinding" contract="ISoapService"/>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" receiveTimeout="00:10:00" sendTimeout="00:10:00">
<readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="16348" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
</binding>
</basicHttpBinding>
</bindings>
I'm not getting any 400 anymore but instead of that 'cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher.' error appeared. Also after adding protocolMapping, my soap methods have disappeared when I open wsdl in browser. Without it my rest method can be seen in the list like this:
<wsdl:port name="BasicHttpBinding_IRestService" binding="i0:BasicHttpBinding_IRestService">
After that I added AddressFilterMode = AddressFilterMode.Any) in attributes of my Service but it doesn't help.
I found a lot of answers here but somehow not a single one help me to resolve this problem.
What did I miss?
I found the solution after I installed WCF for visual studio. All this time I had wrong namespaces in my web.config and had no idea but VS marked it after installing module. I added right namespace and problem went away. I really suggest to install WCF in VS.
The issue boils down to the fact that we fail to host the service in Restful style.
Ordinarily, there are two ways to configure the Restful style service created by Webhttpbinding.
1.Using the service section to configure the interface and implementation.
<services>
<service name="WcfService3.Service1">
<endpoint address="" binding="webHttpBinding" contract="WcfService3.IService1" behaviorConfiguration="rest"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="rest">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
There are two points we should pay attention to. In the service section, we are supposed to use the corresponding interface and implementation.
<service name="WcfService3.Service1">
<endpoint address="" binding="webHttpBinding" contract="WcfService3.IService1"
Adding a webhttp endpoint behavior also is essential then apply it by using Behaviorconfiguration property.
behaviorConfiguration="mybinding"
In the latest feature, we could create a WCF Restful style service with protocol mapping.
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<add binding="webHttpBinding" scheme="http"/>
It should be noted that we need to add an endpoint behavior without a name.
Based on your configuration, since you have multiple interfaces I suggest you remove the service section and host the service with a protocol mapping feature.
1. Remove service section in the configuration.
2. Remove the name of the endpoint behavior.
<system.serviceModel>
<protocolMapping>
<add scheme="http" binding="webHttpBinding"/>
</protocolMapping>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior>
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
Then we could access the service by the below Uri.
basicaddress/service.svc/RestURI
Feel free to let me know if there is anything I can help with.

Creating a wcf web service and returning the xml response in android

I am an android developer. I want to create an android application which fetches the xml response from a WCF web service using soap. I have created a WCF web service, in which it fetches the XML document and return the content of that document. Here I dont know how to consume that content in android. Moreover, I am new to WCF and I am confused whether I am doing it right or wrong. Any help would be appreciated.
IService.cs
namespace WcfXML
{
[ServiceContract (Namespace="http://tempuri.org/")]
public interface IService1
{
[OperationContract, XmlSerializerFormat]
XmlElement GetData();
}
}
Service1.svc
namespace WcfXML
{
public class Service1 : IService1
{
public XmlElement GetData()
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"D:\defaultGraphProperties.xml");
return xmlDoc.DocumentElement;
}
}
}
After creating this, when I run(F5), I am not able to invoke the method. How can I consume this web services in android? Please Help!!!!
You need to add configuration for webHttpBinding in web.config under the <Bindings>.
Then add the below code in web.config under the <System.serviceModel>
<services>
<service name="Test_WcfService.Service1" behaviorConfiguration="ServiceBehavior">
<endpoint address="" binding="webHttpBinding" bindingConfiguration="webHttpBindingConfiguration" behaviorConfiguration="web" contract="Test_WcfService.IService1"></endpoint>
<endpoint address="Service1.svc" binding="basicHttpBinding" bindingConfiguration="basicHttpBindingConfiguration" contract="Test_WcfService.IService1"></endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="webHttpBindingConfiguration" maxReceivedMessageSize="2147483647" />
</webHttpBinding>
<basicHttpBinding>
<binding name="basicHttpBindingConfiguration" maxReceivedMessageSize="2147483647" />
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
After doing this changes in web.config you will be able to consume the wcf service from Browser.
Replace the Test_WcfService.Service1 and Test_WcfService.IService1 with your WCF Service name and interface.
To consume the WCF Service , you will have to do a Soap Request from Android.
Also if possible share your demo wcf service i will make the necessary configuaration changes at my end.

Cannot turn on includeExceptionDetailInFaults for certain WCF service

I have a WCF project with two endpoints. One endpoint "EP1" shows detailed exceptions in the WCF Test Client but "EP2" does not and shows an error message saying:
The server was unable to process the request due to an internal error. For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the configuration behavior) on the server in order to send the exception information back to the client
I am wondering why this is? I have set the web.config in the same way as "EP1" and on the "EP2" web service class I have added:
[ServiceBehavior(IncludeExceptionDetailInFaults = true)]
I can't imagine what could be different. I have double checked the class name is definitely correct. Here is the section of the web config:
<system.serviceModel>
<services>
<service name="Portal.EP1" behaviorConfiguration="debug"></service>
<service name="Portal.EP2" behaviorConfiguration="debug"></service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="debug">
<!-- To avoid disclosing metadata information, set the value below to false before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Am I crazy?

How to determine if I am using a Restful service or not?

I need to create a Restful service for my application. More I dig deep in to this more I get confused. I understand that a Restful service uses http for CRUD operations which makes it faster and lighter. But I am not sure how to determine if a web service is Restful or not.
However I found some help online that claims to be a Restful service but that has some Custombinding type . Here is how the web.config looks like
<system.serviceModel>
<services>
<service behaviorConfiguration="" name="RestRaw.Service1">
<endpoint address="" behaviorConfiguration="web" contract="RestRaw.IService1" binding="customBinding" bindingConfiguration="RawReceiveCapable"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<bindings>
<customBinding>
<binding name="RawReceiveCapable">
<webMessageEncoding webContentTypeMapperType="RestRaw.RawContentTypeMapper, RestRaw, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<httpTransport manualAddressing="true" maxReceivedMessageSize="524288000"
transferMode="Streamed" />
</binding>
</customBinding>
</bindings>
</system.serviceModel>
Is that a Restful service. If yes how can that be determined??
I am confused at the moment any suggestions to clarify my doubt would be really appreciated.
In this particular case you can tell it's a REST style webservice by the added behavior.
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
The webHttp behavior modifies the operation dispatch pipeline and instead of reading a destination action from a SOAP body, it uses the service interface attributes to decide where to route it. Here is a good page on msdn that shows the basics of creating a REST style webservice in WCF. The following example is from that page.
[ServiceContract]
interface ICustomer
{
//"View It" -> HTTP GET
[WebGet( UriTemplate="customers/{id}" )]
Customer GetCustomer( string id ):
//"Do It“ -> HTTP PUT
[WebInvoke( UriTemplate="customers/{id}", Method="PUT" )]
Customer UpdateCustomer( string id, Customer newCustomer );
}
The WebGet attribute matches the GET verb, then the request URI is pattern matched to decide which method to call. Then parts of the URI can be extracted and converted to parameters and passed to the method call. In the second method, UpdateCustomer, the Customer parameter comes from the request body as it's the only parameter that doesn't get matched elsewhere. In order for the request body to be used like this, the webMessageEncoding binding element is used in the custom binding. If you simply use the WebHttpBinding, it does all of this for you. The config you provided is doing it the explicit way.
The web.config file shows a typical WCF application. To check whether it is RESTful, you might learn WCF REST related topics, such as
https://msdn.microsoft.com/en-us/library/dd203052.aspx

Web Service hosted on GoDaddy fails

I have a WCF web service that works on my local machine, both through the debugger, and installed as a service on IIS.
When I install it on my GoDaddy host, this web service fails. The logging call at the beginning of the function is not executed, and the browser receives a 400/Bad Request response.
Other services compiled together with this work as expected, so it is not a matter of the Connection String, web.config, or such.
The URL to call the service is a simple "GET" call:
http://tucansdev.com/TalLimoService.svc/GetTransportationOffers/1,2,1410885561,false
The Operation contract looks like this:
[OperationContract]
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "GetTransportationOffers/{pickupLocID},{dropoffLocID},{pickupTime},{isAsInstructed}")]
List<GetTransportationOffersResult> GetTransportationOffers(string pickupLocID, string dropoffLocID, string pickupTime, string isAsInstructed);
The log on the GoDaddy server confirms the fact that the call was received, but nothing more.
Just to be thorough, here is my service model from web.config:
<system.serviceModel>
<services>
<service name="TalLimoService.TalLimoService" behaviorConfiguration="ServiceBehavior">
<!--Service Endpoints-->
<!-- Unless fully qualified, address is relative to base address supplied above-->
<endpoint address="" binding="webHttpBinding" contract="TalLimoService.ITalLimoService" behaviorConfiguration="web"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true"/>
Worse yet, it used to work. I changed the third parameter from an explicit date to time ticks, which doesn't affect the interface as far as I can tell. When I revert to the old version, I still get the 400 response, so I guess it isn't the code as such. What is it?
NEXT STEP
Since it used to work, I simplified the code to a completely trivial interface, which then had no problems. I then restored all the parameters to the endpoint, but with an empty function.
The first two lines of the function look like this:
List<GetTransportationOffersResult> transList = new List<GetTransportationOffersResult>();
TalLimoDataDataContext tlData = new TalLimoDataDataContext();
When the function has only the first line, everything is fine. The second line causes the service to return Error 400. I would then say that there is something wrong with my .dbml file, but other functions in this web service make the same call, and there is no problem!
It turns out that the problem was in the web.config file after all. On my machine I had:
<connectionStrings>
<add name="DataSourceConnectionString"...
and on the server, for some reason, it was
<connectionStrings>
<add name="TalLimoConnectionString"...
So on my machine it worked, and on the server it didn't. I guess the moral of the story is never assume anything.

Categories