I'm trying to create a service reading the dead-letter from the transactional system dead letter queue.
The service configuration looks like this:
<service name="NotificationDeadLetterQueueService">
<endpoint
address="net.msmq://localhost/system$;DeadXact"
binding="netMsmqBinding"
contract="INotificationService"
/>
</service>
My service interface:
[ServiceContract]
public interface INotificationService
{
[OperationContract(IsOneWay=true)]
[NetDataContractSerializerFormatAttribute]
void HandleNotification(Notification notification);
}
With my service implementation:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class NotificationDeadLetterQueueService : INotificationService
{
#region INotificationService Members
[OperationBehavior(TransactionScopeRequired = true)]
public void HandleNotification(Notification notification)
{
throw new NotImplementedException();
}
#endregion
}
And start the host like this:
ServiceHost serviceHost = new ServiceHost(typeof(NotificationDeadLetterQueueService));
serviceHost.Open();
So far everything looks like described in many books and tutorials, but when I generate dead-letters within the transactional dead-letter queue the service does not get invoked. What is wrong in my service?
Thanks for help
Enyra
I found the problem, which is quite trick. The msmq client endpoint uses a binding configuration with , so the dead-letter queue service also needs a binding which defines the security mode to none.
Related
I have looked through the docs on wcf on azure service fabric but it seems the only examples show how to expose it to other fabric services. I want to expose a wcf endpoint like I would a rest end point, so I can map it to a public IP address.
Any ideas?
I had to solve this exact scenario.
You don't need to return a listener at all. You need to open an endpoint in the 'Service Manifest.xml'. You bind the ssl cert here etc (I'll assume that you know this part).
<Endpoint Name="Test.WcfTypeEndpoint" Protocol="https" Type="Input" CertificateRef="MySSL" Port="44330" />
You can now open Service Hosts and it will route requests to them. Use a strong wildcard in the binding when opening the service - otherwise it won't resolve on the node that it ends up on.
public class InternalBinding : Binding
{
private readonly HttpsTransportBindingElement _transport;
public InternalBinding()
{
_transport = new HttpTransportBindingElement
{
HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
// etc
}
}
}
I'm new to BizTalk and WCF services and am trying to figure out how to use a WCF service to deliver XML data to Biztalk. I think I'm close but when I call the WCF service operation, the operation executes successfully but does not appear to generate any kind of a message in Biztalk. Am I wrong in assuming that simply calling an operation is enough to trigger a message to BizTalk?
Below is my code and some details about my BizTalk configuration:
WCF service:
public interface IService1
{
[OperationContract, XmlSerializerFormat]
XmlDocument GetXMLDocument(string sourceXML);
}
public class Service1 : IService1
{
public XmlDocument GetXMLDocument(string sourceXML)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(sourceXML);
return doc;
}
}
Calling application (button click calls the service):
protected void Button2_Click(object sender, EventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.AppendChild(doc.CreateNode(XmlNodeType.Element, "Patients", "test"));
SendDoc(doc);
}
protected void SendDoc(XmlDocument doc)
{
//use a Service Client Object to call the service
objServiceClientobjService.GetXMLDocument(doc.OuterXml);
}
BizTalk configuration:
Receive Port:
Port type: One-Way
Receive Location:
Type: WCF-Custom with basicHTTP binding
Endpoint Address is the same as the IIS hosted WCF Service
Receive Pipeline Type: XMLReceive
Your implementation is not correct. There is no link between your WCF service and BizTalk. If you want to receive xml in BizTalk then you need to expose either an Orchestration or Xml Schema as WCF service using BizTalk WCF Web Service Publishing Wizard. This gets installed with BizTalk. Please see link for more details: msdn link
The solution I always use, is to expose an endpoint. Take a look at this example:
I have created three assemblies. A web site, a WCF service and a contracts assembly that holds the interfaces that the services implement. I would like to use Castle Windsor to create the services for me on the client (website) so that I do not have to have an endpoint in the web.config of the web site for each service that I wish to use.
I would like to look at the contract assembly and get all the service interfaces in a namespace. Right now for every service I have something like the following when registering the components with the container.
container.Register(Component.For<ChannelFactory<IMyService>>().DependsOn(new { endpointConfigurationName = "MyServiceEndpoint" }).LifeStyle.Singleton);
container.Register(Component.For<IMyService>().UsingFactoryMethod((kernel, creationContext) => kernel.Resolve<ChannelFactory<IMyService>>().CreateChannel()).LifeStyle.PerWebRequest);
and in my web.config I have the setup code.
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="AuthToken" type="MyNamespace.Infrastructure.AuthTokenBehavior, MyNamespace.Contracts" />
</behaviorExtensions>
</extensions>
<behaviors>
<endpointBehaviors>
<behavior>
<AuthToken />
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00">
<readerQuotas maxStringContentLength="2147483647" maxArrayLength="2147483647"></readerQuotas>
<security mode="None" />
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint name="MyServiceEndpoint" address="http://someurl/MyService.svc" binding="wsHttpBinding" contract="MyNamespace.Contracts.IMyService"></endpoint>
</client>
</system.serviceModel>
I end up with multiple service endpoints that all look almost exactly the same and when we deploy onto clients machines they have to set the address of every endpoint even though the base url is the same for every one.
I would like to have a base url in my web.config that is grabbed through code and then have the services registered with the container using reflection on the contracts assembly. I do need the specialised endpoint behaviour that is in the above config file.
Where so I start? the WcfFacility looks great but the doco is a bit lacking...
I agree the docs for the wcf facility are lacking and that is sad because it is a really great tool and it would be a real shame if people didn't use it because they could not get started, so let me see if I can help you out a little bit if I can...
Let's create a three project application that has:
A class library for shared contracts
A console application that acts as a server
A console application that acts as a client
The idea is that we want to be able to use the service names when we register the services and to share a base URL (I think that is what you were asking and if not, hopefully you can extrapolate from here). So, firstly, the shared contracts simply has this in it (nothing special, normal WCF fare):
[ServiceContract]
public interface IMyService1
{
[OperationContract]
void DoSomething();
}
[ServiceContract]
public interface IMyService2
{
[OperationContract]
void DoSomethingToo();
}
Now the server console application looks like this, we firstly implement the service contracts (again nothing special there, just classes implementing interfaces) and then just register them all as services (notice no need for any configuration file here and you can change the way you decide what are services etc using all the options that Windsor gives you - my scheme is a bit limited but it gives you an idea):
namespace Services
{
public class MyService1 : IMyService1
{
public void DoSomething()
{
}
}
public class MyService2 : IMyService2
{
public void DoSomethingToo()
{
}
}
}
//... In some other namespace...
class Program
{
// Console application main
static void Main()
{
// Construct the container, add the facility and then register all
// the types in the same namespace as the MyService1 implementation
// as WCF services using the name as the URL (so for example
// MyService1 would be http://localhost/MyServices/MyService1) and
// with the default interface as teh service contract
var container = new WindsorContainer();
container.AddFacility<WcfFacility>(
f => f.CloseTimeout = TimeSpan.Zero);
container
.Register(
AllTypes
.FromThisAssembly()
.InSameNamespaceAs<MyService1>()
.WithServiceDefaultInterfaces()
.Configure(c =>
c.Named(c.Implementation.Name)
.AsWcfService(
new DefaultServiceModel()
.AddEndpoints(WcfEndpoint
.BoundTo(new WSHttpBinding())
.At(string.Format(
"http://localhost/MyServices/{0}",
c.Implementation.Name)
)))));
// Now just wait for a Q before shutting down
while (Console.ReadKey().Key != ConsoleKey.Q)
{
}
}
}
And that is the server, now how to consume these services? Well, actually that is quite easy, here is a client console application (it references just the contracts class library):
class Program
{
static void Main()
{
// Create the container, add the facilty and then use all the
// interfaces in the same namespace as IMyService1 in the assembly
// that contains the aforementioned namesapce as WCF client proxies
IWindsorContainer container = new WindsorContainer();
container.AddFacility<WcfFacility>(
f => f.CloseTimeout = TimeSpan.Zero);
container
.Register(
Types
.FromAssemblyContaining<IMyService1>()
.InSameNamespaceAs<IMyService1>()
.Configure(
c => c.Named(c.Implementation.Name)
.AsWcfClient(new DefaultClientModel
{
Endpoint = WcfEndpoint
.BoundTo(new WSHttpBinding())
.At(string.Format(
"http://localhost/MyServices/{0}",
c.Name.Substring(1)))
})));
// Now we just resolve them from the container and call an operation
// to test it - of course, now they are in the container you can get
// hold of them just like any other Castle registered component
var service1 = container.Resolve<IMyService1>();
service1.DoSomething();
var service2 = container.Resolve<IMyService2>();
service2.DoSomethingToo();
}
}
That's it - hopefully this will get you started (I find that experimenting and using the intellisense usually gets me where I need to go). I showed you both the service and client sides but you can just use one or the other if you prefer.
You should be able to see where the binding is configured and how I have gone about constructing the URLs so in your case you could easily just pluck your base URL from a configuration file or whatever you want to do.
One last thing to mention is that you can add your custom endpoint behaviour by adding it as an extension to the endpoint, so in the client example you would have something like this:
Endpoint = WcfEndpoint
.BoundTo(new WSHttpBinding())
.At(string.Format("http://localhost/MyServices/{0}", c.Name.Substring(1)))
.AddExtensions(new AuthTokenBehavior())
I am new to WCF and want to know how do I have multiple services in one project and exposing single end point. I did some home work and realized that we can use interfaces to achieve this. But I am unable to proceed on this.
Can you all give you opinion.
Example:
I have services like Employee Service and Customer Service
From client I should access it like IService.IEmployee.GetEmployee(); or IService.ICustomer.GetCustomer().
Hope I made it clear. Please guide me
Each service has always its own endpoint and each implemented service contract within the service requires its own endpoint as well.
You need facade in this case. You will have single service with single contract which will wrap the logic for both Employee.Service and Customer.Service.
The simplest implementation is like:
public interface ICustomerService { ... }
public interface IEmployeeService { ... }
[ServiceContract]
public interface IService : ICustomerService, IEmployeeService { ... }
// Your WCF service
public class Service : IService { ... }
Now Service can either implement both ICustomerService or IEmployeeService interfaces or it can just internally create instances of some implementations and delegate calls like:
public class Service : IService
{
private CustomerService customerService;
public Service()
{
customerService = new CustomerService();
}
public Customer GetCustomer()
{
retunr customerService.GetCustomer();
}
}
If you have a service (implementation), you can expose any number of endpoints for that service. A service implementation class can implement multiple service contracts, e.g.
public class YourServiceImplementation : IEmployeeService, ICustomerService
{
.....
}
Each endpoint you define for this service implementation however requires one single contract to be associated with it - you cannot have a single endpoint that supports multiple contracts at the same time:
<services>
<service name="YourNamespace.YourServiceImplementation">
<endpoint name="Employee"
address="http://YourServer/Services/EmployeeServices.svc"
binding="basicHttpBinding"
contract="YourNamespace.IEmployeeService" />
<endpoint name="Customer"
address="http://YourServer/Services/CustomerServices.svc"
binding="basicHttpBinding"
contract="YourNamespace.ICustomerService" />
</service>
</services>
So if your client needs to access both the employee and the customer service, you would need to add two separate client-side proxies, one for each service contract.
I can work with many WCF bindings, except netMsmqBinding. All I get is:
CommunicationObjectFaultedException: "The communication object, System.ServiceModel.ServiceHost, cannot be used for communication because it is in the Faulted state."
at System.ServiceModel.Channels.CommunicationObject.Close(TimeSpan timeout)
I tried it in a Windows Server 2008 R2 with the following features installed
Message Queueing
Message Queueing Services
Message Queueing Server
Message Queueing Triggers
HTTP Support
Multicasting Support
Message Queueing DCOM Proxy
I tried also to add manually a private Message Queue in the Server Manager but it didn't work.
I am using a Windows Service to host my MSMQ.
My Service Contract is
namespace MyCompany.Services
{
[ServiceContract(Name = "ServiceName",
Namespace = "http://MyCompany/ServiceName")]
public interface IServiceName
{
[OperationContract(IsOneWay = true)]
void Insert(MyData[] data);
}
[DataContract]
public class MyData
{
[DataMember]
public DateTime DateTime { get; set; }
[DataMember]
public double Lat { get; set; }
[DataMember]
public double Lon { get; set; }
[DataMember]
public TimeSpan Timespan { get; set; }
[DataMember]
public Guid Id { get; set; }
[DataMember(IsRequired = false)]
public int? Category { get; set; }
}
}
And my app.config contains
<endpoint
address="net.msmq://localhost/private/ServiceName"
binding="netMsmqBinding"
contract="MyCompany.Services.IServiceName"
bindingConfiguration="tolerant"
behaviorConfiguration="tolerant"
/>
and
<netMsmqBinding>
<binding name="tolerant"
maxReceivedMessageSize="2147483647"
>
<readerQuotas maxArrayLength="2147483647" />
<security mode="None"/>
</binding>
</netMsmqBinding>
The best starting point would be Tom Hollander's three part blog post:
MSMQ, WCF and IIS: Getting them to play nice (Part 1)
MSMQ, WCF and IIS: Getting them to play nice (Part 2)
MSMQ, WCF and IIS: Getting them to play nice (Part 3)
and have a good look at the MSDN docs on Queues in WCF - lots of stuff there, too!
The error you're getting would indicate some problem with the communication channel - something went wrong, the channel has been "faulted", i.e. rendered unusable. There's a ton of reasons that might happen, that's really hard to diagnose from afar with hardly any info.
Check out the resources and see if that helps you a step or two further - if not, we'll have to get a lot more info from you!