I am building a POC for Azure Service Bus Topics using the code given on this blog post: http://blogs.msdn.com/b/tomholl/archive/2011/10/09/using-service-bus-topics-and-subscriptions-with-wcf.aspx However, I am getting following error.
System.TimeoutException: The request has timed out after 00:00:00 milliseconds. The successful completion of the request cannot be determined. Additional queries should be made to determine whether or not the operation has succeeded.
I have done everything as per the Link. Here is my Code, I receive error on this line: ((IChannel)clientChannerl).Open();
var accountEventLog = new AccountEventLog()
{
AccountId = 123,
EventType = "BE",
Date = DateTime.Now
};
ChannelFactory<IAccountEventNotification> factory = null;
try
{
factory = new ChannelFactory<IAccountEventNotification>("Subscribers");
var clientChannerl = factory.CreateChannel();
((IChannel)clientChannerl).Open();
using (new OperationContextScope((IContextChannel)clientChannerl))
{
var bmp = new BrokeredMessageProperty();
bmp.Properties["AccountId"] = accountEventLog.AccountId;
bmp.Properties["EventType"] = accountEventLog.EventType;
bmp.Properties["Date"] = accountEventLog.Date;
OperationContext.Current.OutgoingMessageProperties.Add(BrokeredMessageProperty.Name, bmp);
clientChannerl.onEventOccurred(accountEventLog);
}
((IChannel)clientChannerl).Close();
factory.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Here is my config settings
<behaviors>
<endpointBehaviors>
<behavior name="securityBehavior">
<transportClientEndpointBehavior>
<tokenProvider>
<sharedSecret issuerName="RootManageSharedAccessKey" issuerSecret="Shared Key Here" />
</tokenProvider>
</transportClientEndpointBehavior>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<netMessagingBinding>
<binding name="messagingBinding" sendTimeout="00:03:00" receiveTimeout="00:03:00"
openTimeout="00:03:00" closeTimeout="00:03:00" sessionIdleTimeout="00:01:00"
prefetchCount="-1">
<transportSettings batchFlushInterval="00:00:01" />
</binding>
</netMessagingBinding>
</bindings>
<client>
<endpoint name="Subscribers"
address="sb://Namespace/topicname"
binding="netMessagingBinding"
bindingConfiguration="messagingBinding"
contract="My Contract"
behaviorConfiguration="securityBehavior" />
</client>
Any help will be highly appreciated
I am able to resolve the issue. However, I am going to describe what I learned in this whole exercise.
The token provider added in the behavior is used for Service Bus Authentication with ACS (Active Directory Service)
Namespaces created using Azure Portal don't create an ACS endpoint/ACS authentication by default. When you create a namespace it only creates SAS (Shared Access Signature) by default.
To Authenticate your wcf call with SAS use this Token provider: <sharedAccessSignature keyName="RootManageSharedAccessKey" key="key" />
In case you want to use ACS authentication then create namespace using Azure Power Shell. Following is the PS command to create Namespace with ACS Authentication enabled:
New-AzureSBNamespace "Namespace" "East US" -CreateACSNamespace $true -NamespaceType Messaging
So to resolve my issue I used the Point 3 described above and it started working.
Another thing to look out for, is has someone accidentally left the proxy enabled in your App.config or Web.config? This will produce a similar exception when sending.
Look for something like the following:
<system.net>
<defaultProxy enabled="true" useDefaultCredentials="true">
<proxy autoDetect="false" bypassonlocal="false" proxyaddress="http://127.0.0.1:8888" usesystemdefault="false" />
</defaultProxy>
</system.net>
Related
So i have the below data in app.config of the project that has a serrvice reference:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="P4U" />
<binding name="P4U1">
<security mode="TransportWithMessageCredential" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://*.svc"
binding="basicHttpBinding" bindingConfiguration="P4U" contract=*.ServiceContract"
name="P4U" />
<endpoint address="https://*.svc"
binding="basicHttpBinding" bindingConfiguration="P4U1" contract="*.ServiceContract"
name="P4U1" />
</client>
</system.serviceModel>
I cant use this data in config. Instead, i have to create them in code. I used BasicHttpBinding and it works fine for http calls but i can get it to work for https. I tried basichttps and wshttpbinding. The username and password is send in header. Any idea what to do?
I tried with TransportWithMessageCredential with basichttp and basichttps.
Below detail is from the client document:
For each request a SOAP header is required, like in the sample:
…
<soap:Header>
<Authentication xmlns="http://*">
<User>customer specific, to be provided</User>
<Password>customer specific, to be provided</Password>
</Authentication>
</soap:Header>
Below code is that i have right now. It is the constructor:
private Binding serviceBinding ;
public ShippingService(string url, AuthenticationHeader webAuthenticationHeader, LogHelper logger)
{
authenticationHeader = webAuthenticationHeader;
this.Logger = logger;
var uri = new Uri(url);
if(uri.Scheme== "https")
{
this.serviceBinding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);
}
else
{
this.serviceBinding = new BasicHttpBinding();
}
this.endpointAddress = new EndpointAddress(url);
}
And in the service call method i have the below line:
ServiceContractClient clientService = new ServiceContractClient (serviceBinding, endpointAddress);
The first exception i got was one below when i was using wshttpbinding:
Content Type application/soap+xml; charset=utf-8 was not supported by service https://*ervice.svc. The client and service bindings may be mismatched. For HTTP's.
I changed back to basic and since then i have been only getting the below exception:
The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.
If you end up with getting an exception that doesn’t give a lot of clue on what is the root cause( like the fault state we were getting), do the below steps to guide you find possible solution
Update the web.config to generate service logs
https://learn.microsoft.com/en-us/dotnet/framework/wcf/diagnostics/configuring-message-logging
Run the application so you hit the error
Open the service log to find the root cause
[ServiceLogError]https://imgur.com/a/3wPgo
I got the error: Username is not provided. Even though while debugging, the exception i got was service is in faulted state.
Use the power of google:
https://amadotech.blogspot.in/2009/11/error-username-is-not-provided-specify.html
So in short i had to add the below two lines of code
clientService.ClientCredentials.UserName.UserName = "xyz";
clientService.ClientCredentials.UserName.Password = "123";
Rest of the code remains same
I've got a restful WCF service that's hosted in IIS served up over SSL using a WebHttpBinding and json.
The service now requires authentication/authorization. There appears to be lots of old information that may or may not still be relevant promoting different ways of achieving authentication, but none of them appear to apply to this specific blend of endpoint binding.
I've played with a bunch of different types of bindings and this appears relatively simple to achieve with SOAP based authentication, but not so with json. Most of the information points to the fact that authentication is usurped by IIS, but I've overcome that hurdle.
I'd like to use basic authentication like so (Example Fiddler request):
GET https://secure.dev.myco.local/api/users/v1/0b7478c5-d25a-4039-9cf4-614b2ef4e04d HTTP/1.1
User-Agent: Fiddler
Host: secure.dev.myco.local
Authorization: Basic dGVzdHVzZXI6UEAkJHcwcmQh
I have the following service behavior configuration:
<behavior name="SslBehavior">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<serviceCertificate findValue="CN=*.dev.myco.local" x509FindType="FindBySubjectDistinguishedName" storeLocation="LocalMachine" />
</serviceCredentials>
<serviceAuthenticationManager authenticationSchemes="Basic"
serviceAuthenticationManagerType="Test.Api.TestAuthenticationManager, Test.Api" />
</behavior>
binding definition:
<webHttpBinding>
<binding name="ProductBinding">
<security mode="Transport" />
</binding>
<binding name="UserBinding">
<security mode="Transport" />
</binding>
</webHttpBinding>
and service definition:
<service name="Test.Api.ApiService" behaviorConfiguration="SslServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="https://secure.dev.myco.local/api/"/>
</baseAddresses>
</host>
<endpoint address="products/v1" name="ProductService" contract="Test.Api.Product.V1.IProductService" binding="webHttpBinding" bindingConfiguration="ProductBinding" behaviorConfiguration="ProductEndpointWebHttpBehavior" />
<endpoint address="users/v1" name="UserService" contract="Test.Api.User.V1.IUserService" binding="webHttpBinding" bindingConfiguration="UserBinding" behaviorConfiguration="UserEndpointWebHttpBehavior" />
</service>
My user accounts are to be held in a table in a database, and authentication passes off the credentials to an authentication provider that for all intents and purposes returns either an IIdentity, an IPrincipal or a boolean if the user authenticates. This will then be attached to the context as required. Because of this, I need my application to handle authentication and not just hand off authentication to IIS.
I am successfully able to access the credentials from the HTTP header and authenticate the user by deriving from the authentication manager and overriding the Authenticate method with the following example code - the IPrincipal is generated and attached to the context as I would expect:
public class TestAuthenticationManager : ServiceAuthenticationManager
{
public override ReadOnlyCollection<IAuthorizationPolicy> Authenticate(ReadOnlyCollection<IAuthorizationPolicy> authPolicy, Uri listenUri, ref Message message)
{
var requestProperties =
(HttpRequestMessageProperty)message.Properties[HttpRequestMessageProperty.Name];
var rawAuthHeader = requestProperties.Headers["Authorization"];
AuthenticationHeader authHeader = null;
if (AuthenticationHeader.TryDecode(rawAuthHeader, out authHeader)) ;
{
var identity = new GenericIdentity(authHeader.Username);
var principal = new GenericPrincipal(identity, new string[] {});
var httpContext = new HttpContextWrapper(HttpContext.Current)
{
User = principal,
};
if (httpContext.User != null)
return null;
}
SendUnauthorizedResponse();
return base.Authenticate(authPolicy, listenUri, ref message);
}
private void SendUnauthorizedResponse()
{
HttpContext.Current.Response.StatusCode = 401;
HttpContext.Current.Response.StatusDescription = "Unauthorized";
HttpContext.Current.Response.Headers.Add("WWW-Authenticate", "Basic realm=\"site\"");
HttpContext.Current.Response.End();
}
}
Where I'm coming unstuck is that upon exiting the validate method, my service responds with the following error:
The server encountered an error processing the request. The exception
message is 'The caller was not authenticated by the service.'. See
server logs for more details. The exception stack trace is: at
System.ServiceModel.Dispatcher.AuthenticationBehavior.Authenticate(MessageRpc&
rpc) at
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc&
rpc) at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean
isOperationContextSet)
The service works fine if I remove the authentication reference from the configuration - as you'd expect, but the user is anauthenticated, and thus if I add any authorization to any of the service methods, it won't handle that piece.
The method appears to exit without error. Can anyone shed any light on why I'm getting this exception with this configuration? I've Googled until the cows come home and the information I find all relates to a limited number of variations of other configurations, but none for WebHttpBinding with Json hosted in IIS with SSL.
The line if (httpContext.User != null) return null; is the problem. if the Authenticate method return Null as Authorization policy the Dispatcher will throw exception.
Here the condition is always true and so it will always return null.You need to return a authorization policy instead of null.
I'm just learning how to use WCF and I am trying to write a little HelloWorld program from scratch (both the host and client sides). I've been getting a ProtocolException Unhandled whenever my client tries to use the service, and I can't figure out why. I'm hosting the service using IIS.
Regarding the way I have things set up: I'm doing my best to separate the client, proxy, host, service, and contract as detailed in this video and as outlined in this article. Basically I've got different projects within the solution for each of those.
Here are some different files showing what I'm talking about:
Service
namespace HelloWorld
{
public class HelloWorldService : IHelloWorldService
{
public String GetMessage(String name)
{
return "Hello World from " + name + "!";
}
}
}
Contract
namespace HelloWorld
{
[ServiceContract]
public interface IHelloWorldService
{
[OperationContract]
String GetMessage(String name);
}
}
Proxy
namespace HelloWorld
{
public class Proxy : ClientBase<IHelloWorldService>, IHelloWorldService
{
#region IHelloWorldService Members
public String GetMessage(String name)
{
return Channel.GetMessage(name);
}
#endregion
}
}
Client
namespace Client
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click_1(object sender, EventArgs e)
{
Proxy proxy = new Proxy();
MessageBox.Show(proxy.GetMessage(textBox1.Text));
}
}
}
The client is just a form with a textbox and a button, and it tries to execute GetMessage() using whatever is in the textbox as a parameter. There is another class that actually creates an instance of the form.
Here's my web.config for the website:
Web.config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceTypeBehaviors">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="HelloWorld.HelloWorldService" behaviorConfiguration="MyServiceTypeBehaviors">
<endpoint address="http://localhost:8002/" binding="basicHttpBinding" contract="HelloWorld.IHelloWorldService"/>
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex"/>
</service>
</services>
</system.serviceModel>
</configuration>
And here's my app.config that goes with the client:
app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint address="http://localhost:8002/" binding="basicHttpBinding" contract="HelloWorld.IHelloWorldService" />
</client>
</system.serviceModel>
</configuration>
My svc file is very short, just:
HelloWorldService.svc
<%#ServiceHost Service="HelloWorld.HelloWorldService"%>
I know the service is running, because when I navigate to http://localhost:8002/HelloWorldService.svc in my browser I get the screen that says
You have created a service.
To test this service, you will need to create a client and use it to
call the service.
So here's where the snag happens: the service is running using IIS, I start an instance of the client, the window with the textbox and the button come up, I type in some letters, hit the button, and then the program crashes and I get the ProtocolException Unhandled, (405) Method not allowed. The error happens on this line of the Proxy class:
return Channel.GetMessage(name);
I've been trying to figure this out for hours and hours, and I haven't made much progress. If someone could at least point me in the right direction, I would be very appreciative.
Last thing: I want to write the client and proxy from scratch, without using svcutil.exe.
The reason it works when you go to the base address (.svc) is that this is an HTTP GET operation to get the metadata for the service. When you call a method on your service contract, you're doing a POST operation and more than likely you just don't have this feature enabled. Depending on the .NET version you're targeting, it will be one of these highlighted in red.
You have to specify full address for your service in the endpoint tag of Client configuration.
Like this:
<endpoint address="http://localhost:8002/HelloWorldService.svc" binding="basicHttpBinding" contract="HelloWorld.IHelloWorldService" />
Do not forget to add '.svc' extension after your service name in address attribute of endpoint tag. It worked for me. Hope you will get the solution now.
Client config will look like this:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService"/>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:61569/Service1.svc" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IService" contract="WcfServiceApp.IService1" name="WSHttpBinding_IService"/>
</client>
Ok, found a solution, although I'm not entirely sure why it works. I guess when you are using Cassini or IIS or whatever to host the website, you're not supposed to specify an address in the endpoint in the web.config file. All I had to do was change it to address="" and it started working properly. Be sure to make sure the port your server is hosting the service on matches the code in your app.config file.
You have to specify full address for your service in the endpoint tag of Client configuration
address="http://localhost:8002/HelloWorldService.svc", where you put same endpoint configurations.
It did work for me while I trapped in hell...
Enabling below two components, worked for me.
I write c# code, to dynamic connect to WCF server. If connect will less that 1 minutes it's work perfect. But if remote function work more than 1-2 minutes, it's throw exception. This is my code:
try
{
BasicHttpBinding basicHttpBinding = new BasicHttpBinding()
{
CloseTimeout = TimeSpan.FromMinutes(20),
OpenTimeout = TimeSpan.FromMinutes(20),
ReceiveTimeout = TimeSpan.FromMinutes(10),
SendTimeout = TimeSpan.FromMinutes(10)
};
EndpointAddress endpointAddress = new EndpointAddress("http://***");
IBrowserClicker personService = new ChannelFactory<IBrowserClicker>(basicHttpBinding, endpointAddress).CreateChannel();
Console.WriteLine(personService.TestConnect().Equals("Hello google!"));
}
catch (Exception exception)
{
Console.WriteLine("Error:"+exception);
}
Exception:
Error:System.ServiceModel.FaultException: 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, or turn on tracing as per the Microsoft .NET Framework SDK documentation and inspect the server trace logs.
So, how it's fix?
try to turn on IncludeExceptionDetailInFaults in web.config file to see the exact error. and this is possible duplicate of
Turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> configuration behavior) on the server
This explain as follows, and it worked for me.
In your .config file define a behavior:
<configuration>
<system.serviceModel>
<serviceBehaviors>
<behavior name="debug">
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
...
Then apply the behavior to your service along these lines:
<configuration>
<system.serviceModel>
...
<services>
<service name="MyServiceName" behaviorConfiguration="debug">
</services>
</system.serviceModel>
</configuration>
Please look at it and let me know if you find trouble to activate it.
I'm just learning how to use WCF and I am trying to write a little HelloWorld program from scratch (both the host and client sides). I've been getting a ProtocolException Unhandled whenever my client tries to use the service, and I can't figure out why. I'm hosting the service using IIS.
Regarding the way I have things set up: I'm doing my best to separate the client, proxy, host, service, and contract as detailed in this video and as outlined in this article. Basically I've got different projects within the solution for each of those.
Here are some different files showing what I'm talking about:
Service
namespace HelloWorld
{
public class HelloWorldService : IHelloWorldService
{
public String GetMessage(String name)
{
return "Hello World from " + name + "!";
}
}
}
Contract
namespace HelloWorld
{
[ServiceContract]
public interface IHelloWorldService
{
[OperationContract]
String GetMessage(String name);
}
}
Proxy
namespace HelloWorld
{
public class Proxy : ClientBase<IHelloWorldService>, IHelloWorldService
{
#region IHelloWorldService Members
public String GetMessage(String name)
{
return Channel.GetMessage(name);
}
#endregion
}
}
Client
namespace Client
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click_1(object sender, EventArgs e)
{
Proxy proxy = new Proxy();
MessageBox.Show(proxy.GetMessage(textBox1.Text));
}
}
}
The client is just a form with a textbox and a button, and it tries to execute GetMessage() using whatever is in the textbox as a parameter. There is another class that actually creates an instance of the form.
Here's my web.config for the website:
Web.config
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceTypeBehaviors">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="HelloWorld.HelloWorldService" behaviorConfiguration="MyServiceTypeBehaviors">
<endpoint address="http://localhost:8002/" binding="basicHttpBinding" contract="HelloWorld.IHelloWorldService"/>
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mex"/>
</service>
</services>
</system.serviceModel>
</configuration>
And here's my app.config that goes with the client:
app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint address="http://localhost:8002/" binding="basicHttpBinding" contract="HelloWorld.IHelloWorldService" />
</client>
</system.serviceModel>
</configuration>
My svc file is very short, just:
HelloWorldService.svc
<%#ServiceHost Service="HelloWorld.HelloWorldService"%>
I know the service is running, because when I navigate to http://localhost:8002/HelloWorldService.svc in my browser I get the screen that says
You have created a service.
To test this service, you will need to create a client and use it to
call the service.
So here's where the snag happens: the service is running using IIS, I start an instance of the client, the window with the textbox and the button come up, I type in some letters, hit the button, and then the program crashes and I get the ProtocolException Unhandled, (405) Method not allowed. The error happens on this line of the Proxy class:
return Channel.GetMessage(name);
I've been trying to figure this out for hours and hours, and I haven't made much progress. If someone could at least point me in the right direction, I would be very appreciative.
Last thing: I want to write the client and proxy from scratch, without using svcutil.exe.
The reason it works when you go to the base address (.svc) is that this is an HTTP GET operation to get the metadata for the service. When you call a method on your service contract, you're doing a POST operation and more than likely you just don't have this feature enabled. Depending on the .NET version you're targeting, it will be one of these highlighted in red.
You have to specify full address for your service in the endpoint tag of Client configuration.
Like this:
<endpoint address="http://localhost:8002/HelloWorldService.svc" binding="basicHttpBinding" contract="HelloWorld.IHelloWorldService" />
Do not forget to add '.svc' extension after your service name in address attribute of endpoint tag. It worked for me. Hope you will get the solution now.
Client config will look like this:
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService"/>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:61569/Service1.svc" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IService" contract="WcfServiceApp.IService1" name="WSHttpBinding_IService"/>
</client>
Ok, found a solution, although I'm not entirely sure why it works. I guess when you are using Cassini or IIS or whatever to host the website, you're not supposed to specify an address in the endpoint in the web.config file. All I had to do was change it to address="" and it started working properly. Be sure to make sure the port your server is hosting the service on matches the code in your app.config file.
You have to specify full address for your service in the endpoint tag of Client configuration
address="http://localhost:8002/HelloWorldService.svc", where you put same endpoint configurations.
It did work for me while I trapped in hell...
Enabling below two components, worked for me.