I'm pretty new to web services and I'm trying to configure my WCF service to pull files from another service using the Visual WCF service template.
I've managed to pull everything except for the content data. I've searched and found that I have to use Mtom instead of Text for message encoding. Problem is i'm not sure how to configure my web service to use MessageEncoding = Mtom. I've fiddled with the web.config file but i can't seem to configure it properly.
This is my service interface
[ServiceContract]
public interface IService
{
[OperationContract]
string test(changeData data);
[OperationContract]
RetrieveChangeListResponse GetChangeList();
[OperationContract]
RetrieveChangeTaskListResponse GetTaskList();
[OperationContract]
RetrieveInteractionAttachmentResponse GetFile(string id);
// TODO: Add your service operations here
}
This is my web.config
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="basicHttp" allowCookies="true"
maxReceivedMessageSize="20000000"
maxBufferSize="20000000"
maxBufferPoolSize="20000000"
messageEncoding ="Mtom">
<readerQuotas maxDepth="32"
maxArrayLength="200000000"
maxStringContentLength="200000000"/>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="IService"
behaviorConfiguration="ServiceWithMetadata">
<endpoint name="BasicHttpBinding_IService"
binding="basicHttpBinding"
bindingConfiguration="basicHttp"
contract="IService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceWithMetadata">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
Currently if use this setup I get this error:
Error: Cannot obtain Metadata from localhost:50282/Service.svc If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address. For help enabling metadata publishing, please refer to the MSDN documentation at URI: localhost:50282/Service.svc Metadata contains a reference that cannot be resolved: 'localhost:50282/Service.svc'. Content Type application/soap+xml; charset=utf-8 was not supported by service localhost:50282/Service.svc. The client and service bindings may be mismatched. The remote server returned an error: (415) Cannot process the message because the content type 'application/soap+xml; charset=utf-8' was not the expected type 'text/xml; charset=utf-8'..HTTP GET Error URI: localhost:50282/Service.svc The HTML document does not contain Web service discovery information.
If I remove these settings I get a type mismatch like this:
Client found response content type of 'multipart/related; type="text/xml"; boundary="----=_Part_0_30957184.1421681490926"', but expected 'text/xml'.
I understand there is a config for the WcfTestClient and a config for the actual service, but I don't understand how to properly configure my server side to properly accept Mtom encoding.
Could someone explain how to properly configure the server side binding ? I use BasicHttpBinding, but would also like to use wshHttpBinding for soap 1.2 functionality.
Thanks in advance.
The problem was in the the authentification method used, i was using annonymous instead of basic.
Also you can't have method return types that are proxy data types. If you have such a method you will get an error about class derivation.
Related
I am trying to create a soap web service that will have one web method which takes name as input and will return "hello "+name over HTTPS and will require some certificate to be added in order to be invoked.
I have created a self signed certificate in IIS and have added HTTPS binding with certificate. I have added my application under default web site and have enabled SSL on it.
In the visual studio, I have created WCF service application, enabled SSL on it. Added asmx file that contains only one method in class. Here is the code.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
namespace POCSoap
{
[WebService(Namespace = "https://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class WebService1 : System.Web.Services.WebService
{
[WebMethod]
public string HelloWorld(string name)
{
return "Hello "+name;
}
}
}
I have added binding and service declaration to web.config as well.
<services>
<service name="POCSoap.Service1">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="secureHttpBinding"
contract="POCSoap.IService1"/>
<endpoint address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="secureHttpBinding">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
Still, Call through http is working and call through https is not working. What is missing here.
WCF service is a web service other than XML web service(ASMX). They are different web service specification.
In order to make WCF service work over HTTPS, we should define a service endpoint with transport security like you do and the service contract, service implementation. Moreover, An Https binding in IIS site binding is required for working over HTTPS.
IService.cs
namespace POCSoap
{
[ServiceContract]
public interface IService1
{
string HelloWorld(string name);
}}
Service1.cs
public class Service1 : IService1
{
public string HelloWorld(string name)
{
return "Hello " + name;
}
However, the invocation is completed by a client-side proxy instead of directly sending an HTTP request.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/accessing-services-using-a-wcf-client#add-service-reference-in-visual-studio
As for the ASMX service, we need to call it with a client proxy either. therefore, I would like to know why the call through https is not working when you have already added an https binding in IIS.
To create a Rest API in WCF, which can directly called with a simple Http request(http verb,request body), we need to change the way to create the WCF service.
<system.serviceModel>
<services>
<service name="WcfService3.Service1">
<endpoint address="" binding="webHttpBinding" contract="WcfService3.IService1" behaviorConfiguration="rest"></endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"></endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="rest">
<webHttp helpEnabled="true"/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
At last, what do you mean that requiring certificate to be invoked? you want to authenticate client with a certificate, is that correct? This depends on which web service you use, WCF service or Xml web service.
Feel free to let me know if there is anything I can help with.
I have a Self Hosted WCF Service, which looks like this:
[ServiceContract]
public interface IService {
[OperationContract]
[WebGet]
List<Data> GetData();
//...and much more Methods
}
My App.config looks like this:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<behaviors>
<serviceBehaviors>
<behavior name="MetaInformation">
<serviceMetadata httpGetEnabled="true"
httpGetUrl="http://localhost:8500/MetaInfo"
httpsGetBinding="" />
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="EndpointBehavior">
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MetaInformation" name="Library.WcfService.ServiceModel">
<endpoint address="http://localhost:8500/Service"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBindingSettings"
contract="Library.WcfService.IService"
bindingName="BasicHttpBindingSettings"
behaviorConfiguration="EndpointBehavior"/>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBindingSettings"
closeTimeout="00:50:00"
openTimeout="00:50:00"
sendTimeout="00:50:00"
maxBufferSize="524288"
transferMode="Streamed"
maxReceivedMessageSize="2147483647"
maxBufferPoolSize="2147483647"
messageEncoding="Text">
<readerQuotas maxDepth="2147483647"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
<system.web>
<httpRuntime maxRequestLength="102400"/>
</system.web>
When I run this Server and the Client Applications on my local machine, it's working fine.
But when i try to run the Server Application on another PC, I cannot add a Service Reference at the Client because I get this:
405 Method not allowed Metadata contains a reference that can not be resolved : "http://192.168.178.54:8500/MetaInfo". It was not a
listening to http://192.168.178.54:8500/MetaInfo endpoint present who
could accept the message. This is often caused by an incorrect
address or SOAP action
I tried almost everything I found at the internet but nothing worked.
Switching to IIS or using an other Protocol should be a plan B, i want to keep it self hosted with http.
Please can somebody help me I'm desperate with this Problem.
your operation contract is decorated with [WebGet] attribute, which means you're trying to expose your service as a REST. But your service is using basicHttpBinding as means of building the communication channel which isn't supported because the content type for this binding is soap+xml. You'll need to use WebHttpBinding in this case which is the only binding that supports restful implementation of WCF Services and supports both Xml and Json data types.
[ServiceContract]
public interface IService1
{
[OperationContract]
DataTable GetADUserList(string strUserName, string strFirstName, string strLastName, string strEmail, string domain);
}
I have a WCF service hosted in IIS with the sample service contract above. The service web.config file settings are as below.
Full WCF Web.config file
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding name="notSecureBinding">
<binaryMessageEncoding />
<httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
<binding name="SecureBinding">
<binaryMessageEncoding />
<httpsTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://ServerName.myDomain.org/ADSearcher/Service1.svc"
binding="customBinding"
bindingConfiguration="notSecureBinding"
contract="ADSearcher.IService1"
name="notSecureBinding" />
<endpoint address="http://ServerName.myDomain.org/ADSearcher/Service1.svc"
binding="customBinding"
bindingConfiguration="SecureBinding"
contract="ADSearcher.IService1"
name="SecureBinding" />
</client>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
<system.web>
<customErrors mode="Off"/>
</system.web>
</configuration>
And i'm trying to access the service programmatically as below.
EndpointAddress endpointAddress = new EndpointAddress("http://ServerName.myDomain.org/ADSearcher/Service1.svc");
IService1 ADUser = new ChannelFactory<IService1>("notSecureBinding", endpointAddress).CreateChannel();
The above code is throwing the error below
Could not find endpoint element with name 'notSecureBinding' and contract 'ADSearcher.IService1' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this name could be found in the client element
I can't seem to figure out what i'm doing wrong here or is there a better alternative to access this service programmatically?
In your endpoint, you are specifying a contract of type Data.GetData. The contract is of type IService1, and by default, the contract name should be the typename of the service interface.
If you really want your IService to be referred to as Data.GetData, you can specify the identifying name via the ServiceContractAttribute:
[ServiceContract(ConfigurationName = "Data.GetData")]
public interface IService1
{
[OperationContract]
DataTable GetADUserList(string strUserName, string strFirstName, string strLastName, string strEmail, string domain);
}
Could not find endpoint element with name 'customBinding'....in the
ServiceModel client configuration section
This is because you are defining two client endpoints in your config file. And they are named:
notSecureBinding, and
SecureBinding
So the error message is correct, there is no endpoint element with name "customBinding".
I think you need to do this:
IService1 ADUser = new ChannelFactory<IService1>("<either of the two bindings you defined>").CreateChannel();
Do i need to configure any thing related to WCF in the ASP.NET MVC
application's web.config file?
OK so now I understand. You are hosting the WCF service in your ASP.NET website. And you're trying to call it from somewhere else I assume?
You definitely need to define a <system.serviceModel /> section in your web.config, which will tell IIS how to host your service.
At the moment, the configuration you gave posted above defines to client endpoints. These do not reference service endpoints, but rather is client config designed to allow you to call services. The hint is in the name of the section node: <client />. To define service endpoints that you wish to expose you need to put your endpoint config in a <service /> section. In your case it may only be necessary to change the "client" to "service" to make it all work.
The code which is calling the service may or may not need client configuration in the app.config file. You say you are calling it programatically (although without seeing your full client code I don't know that you are doing enough to satisfy the WCF client call stack), in which case you don't need client config. I hope this makes things clearer for you.
In fear of asking a question which has already been saturated on Stack Overflow, I have been scrolling through possible solutions and am none the wiser as how to achieve what I want to achieve, if it is indeed possible, or whether I have designed my system incorrectly.
This question is not just about finding a solution, but to explain some of WCF’s complexities (and misunderstandings) when configuring/customising different endpoints.
A Typical Scenario: A web-based checkout system where the customer can alter attributes such as qty or size of the product within their basket via making javascript calls back to the server. The server has to be aware of who the user is, so having a session available seems an ideal solution.
WCF definitely seems the way to go, as this scenario can be extended at a future date to support another end-point, such as a mobile app or other service. (Outside the scope of my question, but verifying that I would like to use WCF against a legacy .Net Web Service)
My problem with the above is configuring the endpoints / bindings.
webHttpBinding – This is used so that web scripts can access the service (ie Javascript from a webpage). However it does not support sessions
wsHttpBinding – This supports sessions but not web scripts.
I've played around with various configurations. It seems that I need a combination of the above bindings, or maybe to create a custom binding which supports these elements? If so, are there any nice resources on how to do so? I've tried creating a custom binding and failed miserably!
I've read various comments on other questions that suggest you shouldn't use Sessions via web scripts, that WCF doesn't support it, or that the system being implemented has been incorrectly designed. Firstly, WebServices support this so I find it hard to believe that WCF doesn't, especially as it supports both webscripts and sessions individually (but not together? Out the box maybe...). If I were to use something other than sessions, it would have to be a token based system so that the user can be identified, but surely this is effectively what a session is? I can build this, but it seems like recreating the wheel.
Here is the configuration within my Web.Config. I have setup 3 endpoints to play with; one basic, one supporting sessions and the other supporting webscripts. (The address for the webHttpBinding endpoint is blank, as the service returns an error when in debug mode – I’ve seen this stated by several people too)
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="CustomerServiceAspNetAjaxBehavior">
<enableWebScript />
<!--<webHttp />-->
</behavior>
<behavior name="WebScript">
<enableWebScript />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" />
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<services>
<service behaviorConfiguration="serviceBehavior" name="CustomerService">
<endpoint address="basic" binding="basicHttpBinding" bindingConfiguration="basicBinding"
contract="CustomerService" />
<endpoint address="ws" binding="wsHttpBinding" bindingConfiguration="wsConfig"
contract="CustomerService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="" behaviorConfiguration="CustomerServiceAspNetAjaxBehavior"
binding="webHttpBinding" bindingConfiguration="webConfig" contract="CustomerService" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="basicBinding" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<security mode="None"></security>
<readerQuotas maxStringContentLength="2147483647 "/>
</binding>
</basicHttpBinding>
<wsHttpBinding>
<binding name="wsConfig" transactionFlow="true">
<security mode="None" />
<reliableSession enabled="true" ordered="true"/>
</binding>
</wsHttpBinding>
<webHttpBinding>
<binding name="webConfig">
<security mode="None" />
</binding>
</webHttpBinding>
</bindings>
<client/>
</system.serviceModel>
And this is my service interface, showing that I have set the SessionMode to Allow, and GetSession() which returns the current session id, or null if sessions are unavailable.
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
[ServiceContract(Namespace = "", ConfigurationName = "CustomerService", SessionMode = SessionMode.Allowed)]
public interface ICustomerService
{
[OperationContract()]
[WebGet()]
bool UpdateBasketItem(int index, int productId, int qty, int attribSize);
[OperationContract()]
[WebGet()]
string GetSession();
}
So my long winded question is this.. Can I configure an endpoint to have webscript enabled so that I can access the service via javascript, and also sessions enabled at the same time? I have tested the endpoints individually via the WCF Test Client to see that the 'ws' endpoint does have sessions, and that the blank endpoint using webHttpBinding does not have sessions but is callable from Javascript.
I understand that there may not be an 'out of the box' binding for this, so do I need to create a custom binding, or can I somehow morph the above two endpoints by using a sprinkle of configuration magic?
If you are looking for a service technology that can easily be accessed through JavaScript I would strongly consider Asp.Net WEB API instead. It's a great framework form creating web apis.
It's much more accessible than wcf from a client side perspective and you can leverage standard asp.net concepts. Cookies, Session, Cache etc.
I believe web api was even created in response to the difficulty of doing this in wcf.
I would only consider wcf if you need SOAP support.
I'm truly stumped. I've tried every tool imaginable, checked every resource I can, and still can't make sense of this.
I have a WCF service designed to handle plain old XML requests in a proprietary XML format (this is an old ASMX conversion). I've setup the service using the WCF 3.5 to accept plain HTTP POST requests, and it works beautifully as long as the Content-Type in the request header is not set to "text/xml" (or any other XML or JSON type, such as "text/json" or "application/json").
In other words, if I set the content type of the request to "text" or "text/plain" or even "whatever", the service works as expected. However, when I set the content type to "text/xml", the service fails with an HTTP 400 Bad Request.
And I've failed to find a way to debug the failure to get some more information. The actual service method is never called, and implementing IErrorHandler didn't catch an error either. I'm suspecting something is wrong with my WCF config or with my IIS 7 setup, but I'm absolutely clueless as to what is going on.
Here's my service contract:
using System.ServiceModel;
using System.ServiceModel.Web;
using System.IO;
namespace App.api.v_1_1
{
[ServiceContract]
public interface IPlainXmlWebServiceViaHttpPost
{
[WebInvoke(UriTemplate = "", BodyStyle = WebMessageBodyStyle.Bare, Method = "POST", RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml)]
[OperationContract]
Stream Process(Stream xml);
}
}
And here's my service implementation:
using System.IO;
using System.ServiceModel.Activation;
using App.api.v_1_0;
using System.ServiceModel;
namespace App.api.v_1_1
{
[ServiceBehavior(Namespace = Constants.WebServiceNamespace)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class PlainXmlWebServiceViaHttpPost : IPlainXmlWebServiceViaHttpPost
{
public Stream Process(Stream request)
{
return request.ProcessTextStreamWith(PoxProcessor.Process);
}
}
}
Basically it's just turning the incoming Stream into a string, doing something with that string, and returning a string response converted back into a Stream. The idea is to be able to pass arbitrary XML to the service and return arbitrary XML.
And, finally, here's the relevant portion of the web.config:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<bindings>
<webHttpBinding>
<binding name="poxBinding" maxReceivedMessageSize="655360">
<readerQuotas maxArrayLength="655360" />
<security mode="None">
<transport clientCredentialType="None" />
</security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="REST">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="poxBehavior">
<serviceDebug httpHelpPageEnabled="false" includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="poxBehavior" name="App.api.v_1_1.PlainXmlWebServiceViaHttpPost">
<endpoint address="" behaviorConfiguration="REST" binding="webHttpBinding"
bindingConfiguration="poxBinding" contract="App.api.v_1_1.IPlainXmlWebServiceViaHttpPost" />
</service>
</services>
</system.serviceModel>
I've been trying all sorts of workarounds to get WCF/IIS to cooperate with me, and all have failed. Does anyone know what would cause requesting the expected content types to return HTTP 400, but all other content types to be processed as expected?
Did you use WebServiceHostFactory in your .svc file:
<%# ServiceHost
Factory="System.ServiceModel.Activation.WebServiceHostFactory"
Service="App.api.v_1_1.PlainXmlWebServiceViaHttpPost"
%>
A couple of thoughts for you. You might take a look at the rest starter kit. They have created a bunch of extra stuff to help with building restful services and have a ton of great examples.
The other thing to try when trouble shooting wcf services is to turn on messaging logging. You can do that in your config file like this:
<system.serviceModel>
<diagnostics>
<messageLogging logMalformedMessages="true" logMessagesAtServiceLevel="false"
logMessagesAtTransportLevel="true" />
</diagnostics>
The log files can be read with SvcTraceViewer.exe (My is located here: C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin). I believe this tool comes with the Windows SDK. The config editor (SvcConfigEditor.exe) found in the same location can be used to help edit your web.config. There are other options for what to log if you click on the 'Diagnostics' folder after loading your config file into the editor.