Getting Error Access denied while consuming WSDL endpoint - c#

I need to access web service which required HTTP basic authentication and I consumed successfully using SoapUI.
SoapUI
Now I need to implement in .net.
I created a new C# Console project in Visual Studio and added a web reference for https://itestapi.tracelink.com/soap/snx/snrequest?wsdl
Below is my code and I am getting Access Denied
C# code
ServiceReference1.snrequestClient snx = new ServiceReference1.snrequestClient();
snx.ClientCredentials.UserName.UserName = "abc#gmail.com";
snx.ClientCredentials.UserName.Password = "xyz#2018";
ServiceReference1.objectKey objectKey = new ServiceReference1.objectKey
{
Name = ServiceReference1.objectIdentifierType.GTIN,
Value = "1111111"
};
ServiceReference1.ReferenceDocuments ReferenceDocuments = new ServiceReference1.ReferenceDocuments();
snx.serialNumbersRequest("11111", "11111", ServiceReference1.idType.GS1_SER, ServiceReference1.encodingType.SGTIN, 2, objectKey, "", ReferenceDocuments);
App.config
<bindings>
<basicHttpBinding>
<binding name="snrequestPortBinding">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
<binding name="snrequestPortBinding1" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://itestapi.tracelink.com:443/soap/snx/snrequest"
binding="basicHttpBinding" bindingConfiguration="snrequestPortBinding"
contract="ServiceReference1.snrequest" name="snrequestPort" />
</client>

Related

C# ASMX Service throwing The content type text/html; charset=UTF-8 of the response message does not match the content type error

I have added a ASMX service reference to my project by doing right click on the root --> add service reference.
I have it like this on my web.config file:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="xxx" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="serviceaddress"
binding="basicHttpBinding" bindingConfiguration="xxx"
contract="xxx" name="xxx" />
</client>
</system.serviceModel>
This service has a method that receives a string with a username and validates if it exists.
The problem is that I'm testing it on Postman and it's returning the following error message:
The content type text/html; charset=UTF-8 of the response message does not match the content type
I've already checked on other posts similar like this one but I'm not able to find the solution.
Here's the method that I invoke which is throwing the error:
public static List<UserInformation> GetUsersByUserName(string userName)
{
try
{
var usersServiceClient = new LDapServicesSoapClient();
var requestMessage = new LDapUserNameLookupRequest();
requestMessage.UserName = userName;
requestMessage.AccessKey = "secretkey";
var response = usersServiceClient.LDapGetUserByUserName(requestMessage);
return response.Users.ToList();
}
catch (CommunicationException e)
{
if (e.InnerException is QuotaExceededException)
{
throw new Exception("We have found many users, please write another filter");
}
else
{
throw new Exception(e.Message, e);
}
}
}
Adding this configuration to my web.config file did the magic:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="LDapServicesSoap" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" allowCookies="false" bypassProxyOnLocal="false" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text">
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
<message clientCredentialType="Certificate" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="address"
binding="basicHttpBinding" bindingConfiguration="LDapServicesSoap"
contract="LDapServices.LDapServicesSoap" name="LDapServicesSoap" />
</client>
</system.serviceModel>

Programmatically define WCF Endpoints with Behaviours

Can anyone show me how to programmatically create WSHttpBindings with Endpoint behaviours?
This is what was generated from WCF Add Service references to 6 WebServices which I manually editted to add behaviours so that all the endpoints uses the same behaviour .
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="epBehaviour">
<clientCredentials>
<clientCertificate findValue="This is my TEST Cert" storeLocation="LocalMachine" x509FindType="FindBySubjectName" storeName="My" />
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IQuote" messageEncoding="Mtom">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="Certificate" establishSecurityContext="false" />
</security>
</binding>
<binding name="WSHttpBinding_ICommit" messageEncoding="Mtom">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="Certificate" establishSecurityContext="false" />
</security>
</binding>
<binding name="WSHttpBinding_IRetrieve" messageEncoding="Mtom">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="Certificate" establishSecurityContext="false" />
</security>
</binding>
<binding name="WSHttpBinding_IInfo" messageEncoding="Mtom">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="Certificate" establishSecurityContext="false" />
</security>
</binding>
<binding name="WSHttpBinding_IPurge" messageEncoding="Mtom">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="Certificate" establishSecurityContext="false" />
</security>
</binding>
<binding name="WSHttpBinding_ISearch" messageEncoding="Mtom">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="Certificate" establishSecurityContext="false" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://my.service.com/WCFServices/Info.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IInfo" contract="InfoWcfWS.IInfo" name="WSHttpBinding_IInfo" />
<endpoint address="https://my.service.com/WCFServices/Quote.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IQuote" contract="QuoteWcfWS.IQuote" name="WSHttpBinding_IQuote" />
<endpoint address="https://my.service.com/WCFServices/Commit.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ICommit" contract="CommitWcfWS.ICommit" name="WSHttpBinding_ICommit" />
<endpoint address="https://my.service.com/WCFServices/Retrieve.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IRetrieve" contract="RetrieveWcfWS.IRetrieve" name="WSHttpBinding_IRetrieve" />
<endpoint address="https://my.service.com/WCFServices/Purge.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IPurge" contract="PurgeWcfWS.IPurge" name="WSHttpBinding_IPurge" />
<endpoint address="https://my.service.com/WCFServices/Search.svc" behaviorConfiguration="epBehaviour" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ISearch" contract="SearchWcfWS.ISearch" name="WSHttpBinding_ISearch" />
</client>
</system.serviceModel>
Currently with the generated Proxy from the "Add Service" and adding the behaviour "epBehaviour" which is referenced in the endpoints as a behaviourConfiguration, I can make calls to the endpoints.
Now, my next step is to define the behaviour part and the URL as configurations (May be in the of the web.config) so that I can have different config for Staging and Production.
So my sample Staging config will have the URL defined as below
<appSettings>
<add key="ServiceUrl.Tls12.Quote" value="https://my.service.com/WCFServices/Quote.svc" />
<add key="ServiceUrl.Tls12.Commit" value="https://my.service.com/WCFServices/Commit.svc" />
<add key="ServiceUrl.Tls12.Retrieve" value="https://my.service.com/WCFServices/Retrieve.svc" />
<add key="ServiceUrl.Tls12.Info" value="https://my.service.com/WCFServices/Info.svc" />
<add key="ServiceUrl.Tls12.Purge" value="https://my.service.com/WCFServices/Purge.svc" />
<add key="ServiceUrl.Tls12.Search" value="https://my.service.com/WCFServices/Search.svc" />
</appSettings>
So if I'm consuming the "Info" WebService, my code should be something like
//Code is missing how to define all the specifics like behaviours.
WSHttpBinding binding = new WSHttpBinding();
EndpointAddress endpoint = new EndpointAddress(new Uri(ConfigurationManager.AppSettings["ServiceUrl.Tls12.Info"]));
InfoWcfWS.InfoClient proxyNew = new InfoWcfWS.InfoClient(binding, endpoint);
In Summary, given the generated config after an "Add Service", to generate my Proxy Classes, I would like to remove all the config generated by VS and define my own config which will hold the URL; Everything else like endpoints URI, behaviours ..etc should be instantiated programmatically.
Thanks
You have to create instances of the behavior you need either from the System.ServiceModel.Description namespace or create them yourself and then add them to a ChannelFactory.
For your example you create a ChannelFactory for the interface you want and any binding you prefer. You then instantiate a ClientCredentials behavior, configure any of the settings you need on it and add it to the EndPointBehaviors of the ChannelFactory. Then you're ready to create a clientchannel that will give you an object that implements your service interface. You can use that similar as the generated client.
// binding
var binding = new WSHttpBinding();
// using System.ServiceModel
var channelFactory = new ChannelFactory<InfoWcfWS.IInfo>(binding);
// using System.ServiceModel.Description
var endpointClientbehavior = new ClientCredentials();
endpointClientbehavior.ClientCertificate
.SetCertificate(
"This is my TEST Cert",
StoreLocation.LocalMachine,
StoreName.My);
// add the behavior to the endpoint
channelFactory.Endpoint.EndpointBehaviors.Add(endpointClientbehavior);
// done configuring;
channelFactory.Open();
var endpoint = new EndpointAddress(
new Uri(ConfigurationManager.AppSettings["ServiceUrl.Tls12.Info"]));
// create the clientChannel
var client = channelFactory.CreateChannel(endpoint);
client.Open();
// client implements the operations on InfoWcfWS.IInfo
In the end, I found a simpler way of achieving this - This is one of the method Info I'm accessing:
WSHttpBinding binding = new WSHttpBinding();
EndpointAddress endpoint = new EndpointAddress(new Uri("https://my.service.com/WCFServices/Info.svc"));
binding.Name = "WSHttpBinding_IInfo";
binding.MessageEncoding = WSMessageEncoding.Mtom;
binding.Security = new WSHttpSecurity();
binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
binding.Security.Transport = new HttpTransportSecurity();
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.Security.Message = new NonDualMessageSecurityOverHttp();
binding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
binding.Security.Message.EstablishSecurityContext = false;
InfoClient proxy = new InfoClient(binding, endpoint);
proxy.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindBySubjectName, "This is my TEST Cert");
object response = proxy.ServiceMethod();

Pass Windows credentials to remote https WCF service

I need some help, I'm trying to pass windows credentials to a WCF service. In the IIS only Windows authentication is enabled for those service and runs over https.
The server side config is:
<system.serviceModel>
<protocolMapping>
<add scheme="https" binding="basicHttpBinding" bindingConfiguration="httpsBinding"/>
</protocolMapping>
<bindings>
<basicHttpBinding>
<binding name="httpsBinding">
<security mode="Transport">
<transport clientCredentialType="Windows"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
and in the client side:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IMyService" maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="Transport">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://myserver.net:4343/MyService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMyService"
contract="MyServiceReference.IMyService" name="BasicHttpBinding_IMyService" />
</client>
I'm trying to consume the service on this way:
Client = new MyServiceClient();
BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
binding.MaxReceivedMessageSize = int.MaxValue;
binding.MaxBufferPoolSize = long.MaxValue;
binding.MaxBufferSize = int.MaxValue;
EndpointAddress ep = new EndpointAddress("https://myserver.net:4343/MyService.svc");
Client = new COMINTSServiceClient(binding, ep);
Client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Identification;
Client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
Client.Open();
Array[] obj = Client.RandomMethod();
This code doesn't work for me:
Client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Identification;
Client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
In the service when ask for the user who is calling to the service using ServiceSecurityContext.Current.WindowsIdentity.Name allways get: ISS APPPOOL\ASP.NET v4.0 instead of the domain\user who is calling
The only way to make it work is write the username and password instead DefaultNetworkCredentials.
Client.ClientCredentials.Windows.ClientCredential.UserName = "DOMAIN\\user";
Client.ClientCredentials.Windows.ClientCredential.Password = "passw";
But I don't want a user/passw hardcoded.
Any help please?
Try:
Client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
Keep the assignment from CredentialCache.
I faced with similar issue - "ServiceSecurityContext.Current.WindowsIdentity.Name" on the server side returned wrong username, not Current Windows User on the client side. Turns out "Client.ClientCredentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials" may get credentials from Windows Credential Manager:
I failed to find a solution to instruct WCF to avoid grabbing credentials from that storage. The workaround was to check if some credentials are stored for that IP address and remove them. I used "https://www.nuget.org/packages/CredentialManagement" for checking and removing. Here is the code:
var creds = new Credential();
creds.Type = CredentialType.DomainPassword;
creds.Target = address.Uri.Host;//address is WCF EndpointAddress
if (creds.Load() && creds.Username != System.Security.Principal.WindowsIdentity.GetCurrent().Name)
{
creds.Delete();
}

WCF exception--Faulted state

I added the WCF service reference to my project. Next step is to create a channel from the code.
WSHttpBinding bindingDialingType = new WSHttpBinding();
EndpointAddress endingPointDialingType = new EndpointAddress("http://wsvc.corporate.my.com/International/DialingService.svc");
ChannelFactory<IDialingService> iDialingServiceChannelFactory = new ChannelFactory<IDialingService>(bindingDialingType, endingPointDialingType);
IDialingService instanceIDialingService = iDialingServiceChannelFactory.CreateChannel();
Because I met an exception, so I guess that something wrong with my channel factory code.
The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.
To capture the exception, I had the code.
My app.config is:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_iLuCRE" />
</basicHttpBinding>
<wsHttpBinding>
<binding name="WSHttpBinding_IDialingService">
<security mode="None" />
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://wsvc.corporate.my.com/LuCRE/LuCRE.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_iLuCRE"
contract="LuCRE.iLuCRE" name="BasicHttpBinding_iLuCRE" />
<endpoint address="http://wsvc.corporate.my.com/International/DialingService.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IDialingService"
contract="DialingService.IDialingService" name="WSHttpBinding_IDialingService" />
</client>
</system.serviceModel>
I used WCFTestClient to test it, however the service does work. I added the service reference to my project and I don't know the code details.
Updated:
If I used the code
DialingServiceClient client = new DialingServiceClient();
Then call the method through client, then everything is fine. Why?
Your binding element security is None. You need to also mention it when defining programmatically.
WSHttpBinding bindingDialingType = new WSHttpBinding
{ Security = new WSHttpSecurity { Mode = SecurityMode.None } };

How to pass user credentials to web service?

I am consuming a webservice using WSDL in windows application. When I try to use method, i get the following error:-
The HTTP request is unauthorized with client authentication scheme
'Anonymous'. The authentication header received from the server was '"
{"The remote server returned an error: (401) Unauthorized."}
I have user credentials but don't know how to pass it using c# code in windows application.
Here is the how it is working for me:-
Config file setting looks like this:-
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="bindingName" >
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic" proxyCredentialType="None" realm=""/>
<message clientCredentialType="UserName" algorithmSuite="Default"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://10.10.10.10:1880/testpad/services/Testwebservice"
binding="basicHttpBinding" bindingConfiguration="bindingName"
contract=testService.GetData" name="test_Port1" />
</client>
</system.serviceModel>
</configuration>
and here i am passing user credentials:-
var ser = new GetDataClient();
ser.ClientCredentials.UserName.UserName = "userid";
ser.ClientCredentials.UserName.Password = "Pa$$word1";
You can try to genereate your service client proxy using the method mentioned here. Once you have an instance of your WCF client proxy, it will have a property ClientCreditials which you can populate as needed.
Hope this helps.

Categories

Resources