How to use MSMQ in WCF? - wcf

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!

Related

Protect WCF from fiddler (MITM) (PCL XAMARIN FORMS)

I have xamarin forms project using portable class library.
In that PCL I reference my WCF service which is hosted in some server.
The wcf binding is Basichttpbinding with security transport as PCL does not support wshttpbinding.
Also the wcf is use https and i have a valid certificate for that.
I want to secure the messages because now if i install some kind of application fiddler or packed monitor in my android every call to my service i can see the xml data in readable format.
I thought by using https i was protecting that.
I try use wcf TransportWithMessageCredential but it failed to login to my service because xamarin does not yet support this combination
So: ( after research i found out that )
PCL does not support wshttpbinding only basicHttpBinding
Xamarin.Forms basicHttpBinding does not support message security but only
TransportCredentialOnly
And
Xamarin does not support TransportWithMessageCredential but only
transport security but transport security not protecting the data from MITM.
How others working with xamarin forms and protect these data?
Do i missed anything?
Any suggestions?
EDITED
I am trying to encrypt the xml request before send to service but fails every time i change the message e.g from xml to encoded characters (i guess because the server fails to recognize the schema )
I have implement IClientMessageInspector at the client Side as also IDispatchMessageInspector at the server side.
I need some help how i can send the xml request encrypted to the server.. if i do it here then i can decode it from service side ( server)
At the client side i have the following
Public Function BeforeSendRequest(ByRef request As Message, channel As IClientChannel) As Object Implements IClientMessageInspector.BeforeSendRequest
Dim Binding As New BasicHttpBinding(BasicHttpSecurityMode.Transport)
Dim ms As MemoryStream = New MemoryStream(System.Text.Encoding.UTF8.GetBytes(EncryptedData(request.ToString)))
Dim RQuotas As Xml.XmlDictionaryReaderQuotas = Binding.ReaderQuotas
Dim reader = Xml.XmlDictionaryReader.CreateTextReader(ms, RQuotas)
request = Message.CreateMessage(reader, Int32.MaxValue, request.Version)
Return Nothing
End Function
I am not sure if i do it correctly. Any help welcome.
Fiddler only decrypts Https Traffic if you accept its certificate, it basically acts a man in the middle and handles all the calls from the service to your app, there is some useful info here https://docs.telerik.com/fiddler/Configure-Fiddler/Tasks/DecryptHTTPS ,
On your second update of the question, you would need to create a container that will house all your messages,
that way you can decrypt and encrypt the data as you see fit,
A simple example can be found at https://misaxionsoftware.wordpress.com/2011/07/29/secure-restful-web-service-by-wcf-web-api-no-https-seriously/
You can customise it as much as possible
Here is the message that is defined in the link above
Message
public class Message
{
public string AppId { get; set; }
public string Data { get; set; }
public string Id { get; set; }
public string TimeStamp { get; set; }
public byte[] GenerateFingerprint();
public bool ValidateHash(byte[] fingerprint);
}
Encrypted Message
public class EncryptedMessage
{
public string AppId { get; set; }
public byte[] Fingerprint { get; set; }
///<summary>
/// The 3DES key used to encrypt/decrypt the message
/// </summary>
public byte[] Key { get; set; }
///<summary>
/// Encrypted message
/// </summary>
public byte[] Message { get; set; }
}
IEncryptionHelper
public interface IEncryptionHelper
{
EncryptedMessage Encrypt(Message message);
Message Decrypt(EncryptedMessage encryptedMessage);
}

Using Swagger with WCF REST

I have a WCF REST based service that I would like to add Swagger to. I have installed Swagger.NET package, my project is using .NET 4.0. I have also enabled XML documentation, etc... but now I am not sure the best route from here.
When i launch http://localhost/SwaggerUI/index.html I get the default page with the http://YOUR-URL-HERE:PORT/api/swagger. I am not sure what url should go here. I did enable help of the service via: <standardEndpoint name="" helpEnabled="true" /> which does give me the ugly page here: http://localhost/api/help -- when i plug that into Swagger i just get the result:
200 : OK http://localhost/api/help
What is the best way to proceed, i am not using WebApi but have many of the features available if that helps.
As of December 2015, there is an implementation of Swagger for Wcf now. You should check this out - Swagger for WCF - SwaggerWcf
Currently there are no implementations of Swagger for WCF. You will either need to implement your own by following the spec from https://github.com/wordnik/swagger-core/wiki, or wait patiently for someone to implement one for you.
I currently have an implementation in progress, but it's not quite ready for primetime. The basic spec is deceptively simple, but fitting it to WCF is a definite challenge.
I tried to implement swagger for WCF in my application as the implementation is different as we implanted for web API(simpler). I will tell you how its different and how it works step by step:-
**1. Why Swagger4Wcf**
----------------------
•Manually writing yaml description for swagger and maintain it especially WCF services are boring.
•There is a nuget package called Swagger4WCF that automatically generates yaml description for swagger 2.0 for each interface matching attributes used by WCF (ServiceContract/OperationContract/WebGet/WebInvoke).
2. How Swagger Works in the Background
--------------------------------------
Swagger4WCF uses NuPack post build pattern to trigger at build time.
https://www.codeproject.com/Tips/1190360/How-to-setup-a-managed-postbuild-without-scripting
3.At build time, it will detect assemblies present in output directory, open them with mono.cecil (to reflect assemblies) to generate expected yaml description for swagger 2.0.
Swagger4WCF detects **WebGet/WebInvoke** to provide Verb/Method in serialization style in yaml.
Steps to implement Swagger in your application:-
1. Install SwaggerWcf package
2. Configure WCF routes
We have to add the route in the Application_Start method inside Global.asax
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Add(new ServiceRoute("v1/rest", new WebServiceHostFactory(), typeof(BookStore)));
RouteTable.Routes.Add(new ServiceRoute("api-docs", new WebServiceHostFactory(), typeof(SwaggerWcfEndpoint)));
}
Note: Edit Web.config and add the following (if it doesn't exist yet) inside the system.serviceModel block
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
3. Configure WCF response auto types (optional)
We have to add the following to Web.config. This will allow the WCF service to accept requests and send replies based on the Content-Type headers.
<behavior name="webHttpBehavior">
<webHttp defaultOutgoingResponseFormat="Json" automaticFormatSelectionEnabled="true"/>
</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>
4. Decorate WCF services interfaces
For each method, we have to configure the WebInvoke or WebGet attribute, and add a SwaggerWcfPath attribute.
[SwaggerWcfPath("Get book", "Retrieve a book from the store using its id")]
[WebGet(UriTemplate = "/books/{id}", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
Book ReadBook(string id);
5. Decorate WCF services class
• Add the SwaggerWcf and AspNetCompatibilityRequirements attributes to the class providing the base path for the service.
• For each method, add the SwaggerWcfTag to categorize the method and theSwaggerWcfResponse for each possible response from the service.
[SwaggerWcfTag("Books")]
[SwaggerWcfResponse(HttpStatusCode.OK, "Book found, value in the response body")]
[SwaggerWcfResponse(HttpStatusCode.NoContent, "No books", true)]
public Book[] ReadBooks()
{
}
6. Decorate data types used in WCF services
[DataContract]
[Description("Book with title, first publish date, author and language")]
[SwaggerWcfDefinition(ExternalDocsUrl = "http://en.wikipedia.org/wiki/Book", ExternalDocsDescription = "Description of a book")]
public class Book
{
[DataMember]
[Description("Book ID")]
public string Id { get; set; }
[DataMember]
[Description("Book Title")]
public string Title { get; set; }
[DataMember]
[Description("Book First Publish Date")]
public int FirstPublished { get; set; }
[DataMember]
[Description("Book Author")]
public Author Author { get; set; }
[DataMember]
[Description("Book Language")]
public Language Language { get; set; }
}
That's it wcf for Swagger implemented.
Please free if you face any issue.
Thanks,
Abhi

NServiceBus Sagas using NHibernate - Unable to connect to remote server

I am trying to setup NServiceBus Sagas using NHibernate persistence, but I think I have something configured incorrectly because I'm getting an error connecting to a service at 127.0.0.1:8080. I am able to get my saga to handle the command message, but after a few seconds the error message below appears in the console window and then the same command is fired again causing the handler in the saga to be invoked again. This happens repeatedly as long as I allow the application to run. I can tell NHibernate is connecting to my database because it creates a table for the saga data, however nothing is ever persisted in that table.
I think there is an error persisting the saga data, and my guess is that it may be trying to use the default RavenDb saga persistence but I'm not sure why this would be.
The error message I receive is the following:
WARN
NServiceBus.Unicast.Transport.Transactional.TransactionalTransport
[(null)] <(null)> - Failed raising 'transportmessage received' event
for message with ID=3753b476-7501-4fd8-90d0-b10aee95a578\22314
System.Net.WebException: Unable to connect to the remote server --->
System.Net.Sockets.SocketException: No connection could be made
because the target machine actively refused it 127.0.0.1:8080 at
System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot,
SocketAddress socketAddress) at
System.Net.Sockets.Socket.InternalConnect(EndPoint remoteEP) at
System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure,
Socket s4, Socket s6, Socket& socket, IPAddress& address,
ConnectSocketState state, IAsyncResult asyncResult,Exception&
exception) --- End of inner exception stack trace --- at
NServiceBus.Unicast.UnicastBus.HandleTransportMessage(IBuilder
childBuilder, TransportMessage msg) at
NServiceBus.Unicast.UnicastBus.TransportMessageReceived(Object sender,
TransportMessageReceivedEventArgs e) at
System.EventHandler`1.Invoke(Object sender, TEventArgs e) at
NServiceBus.Unicast.Transport.Transactional.TransactionalTransport.OnTransportMessageReceived(TransportMessage
msg)
A sample of the saga I am trying to use is (nothing fancy here, same thing happens whether or not I actually do something in the Handle method):
public class ItemSaga : Saga<ItemData>, IAmStartedByMessages<CreateItemCommand>
{
public void Handle(CreateItemCommand message)
{
}
}
public class ItemData : ISagaEntity
{
public Guid Id { get; set; }
public string Originator { get; set; }
public string OriginalMessageId { get; set; }
}
My endpoint configuration looks like this:
public class EndpointConfig : IConfigureThisEndpoint, AsA_Publisher, IWantCustomInitialization
{
public void Init()
{
var container = new UnityContainer();
container.AddNewExtension<Domain.UnityExtension>();
Configure.With()
.UnityBuilder(container)
.JsonSerializer()
.Log4Net()
.MsmqSubscriptionStorage()
.MsmqTransport()
.PurgeOnStartup(true)
.UnicastBus()
.ImpersonateSender(false)
.DisableTimeoutManager()
.NHibernateSagaPersister()
.CreateBus()
.Start(() => Configure.Instance.ForInstallationOn<NServiceBus.Installation.Environments.Windows>().Install());
}
}
And my app.config looks like this:
<MessageForwardingInCaseOfFaultConfig ErrorQueue="error"/>
<MsmqTransportConfig NumberOfWorkerThreads="1" MaxRetries="5"/>
<NHibernateSagaPersisterConfig UpdateSchema="true">
<NHibernateProperties>
<add Key="connection.provider" Value="NHibernate.Connection.DriverConnectionProvider"/>
<add Key="connection.driver_class" Value="NHibernate.Driver.Sql2008ClientDriver"/>
<add Key="connection.connection_string" Value="Data Source=(localdb)\v11.0;Integrated Security=True;AttachDbFileName=|DataDirectory|\App_Data\EventStore.mdf"/>
<add Key="dialect" Value="NHibernate.Dialect.MsSql2012Dialect"/>
</NHibernateProperties>
</NHibernateSagaPersisterConfig>
<connectionStrings>
<add name="EventStore" connectionString="Data Source=(localdb)\v11.0;Integrated Security=True;AttachDbFileName=|DataDirectory|\App_Data\EventStore.mdf"
providerName="System.Data.SqlClient" />
</connectionStrings>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="NHibernate" publicKeyToken="aa95f207798dfdb4" />
<bindingRedirect oldVersion="0.0.0.0-3.3.0.4000" newVersion="3.3.1.4000" />
</dependentAssembly>
</assemblyBinding>
</runtime>
Just a couple of notes:
This is from a sample app that I am using to test this functionality. It uses a local database file attached to localdb, however my full application using SQL Server 2012 is exhibiting the same behavior. I also had to add a dependenteAssembly entry for NHibernate because the NServiceBus.NHibernate NuGet package currently binds to an older assembly version (as of this posting).
As you can see, I am also using Unity as my IOC, but I have replicated this with a project using Ninject as well. I am using EventStore for my domain storage which is working great. I have command handlers that handle the command and publish events through EventStore to be handled by other processes. However, I have tried disabling all of those leaving me with just my Saga as a command handler and I still get the same error.
Does anyone have any ideas of what I may be doing wrong?
I have found a workaround to my problem. It seems to be an issue with using the built-in NServiceBus profiles. I was not specifying a profile in the command line arguments of the host, so by default it was loading the NServiceBus.Production profile. The Production profile, by default, uses RavenDB for all persistence.
Looking at the NServiceBus source on GitHub, the Production Profile Handler contains the following in the ProfileActivated method:
Configure.Instance.RavenPersistence();
if (!Configure.Instance.Configurer.HasComponent<ISagaPersister>())
Configure.Instance.RavenSagaPersister();
if (!Configure.Instance.Configurer.HasComponent<IManageMessageFailures>())
Configure.Instance.MessageForwardingInCaseOfFault();
if (Config is AsA_Publisher && !Configure.Instance.Configurer.HasComponent<ISubscriptionStorage>())
Configure.Instance.RavenSubscriptionStorage();
A couple of things to note here:
The profile will always call RavenPersistence() on the
Configure instance. I have not dug into the inner workings of that
method to see if it will actually bypass configuring Raven if other
persistence is already defined, but it will always run this method.
When I attach to the NServiceBus source and debug through
this code, in the second line HasComponent returns
false causing the RavenSagaPersister configuration to be run. This
happens even if I have NHibernateSagaPerister is defined in the endpoint
configuration.
I'm not sure if this behavior is by design, a bug, or misconfiguration on my part. However my workaround was to create my own profile. I had to move the NHibernate configuration calls from my endpoint config to my new profile, but once I did that I was able to use NHibernate persistence without errors.
My custom profile looks like the following (I borrowed the logging handler from the Production profile's logging handler):
public class MyProfile : IProfile
{
}
internal class MyProfileProfileHandler : IHandleProfile<MyProfile>, IWantTheEndpointConfig
{
void IHandleProfile.ProfileActivated()
{
Configure.Instance.NHibernateUnitOfWork();
Configure.Instance.NHibernateSagaPersister();
Configure.Instance.DBSubcriptionStorage();
Configure.Instance.UseNHibernateTimeoutPersister();
}
public IConfigureThisEndpoint Config { get; set; }
}
public class MyProfileLoggingHandler : IConfigureLoggingForProfile<MyProfile>
{
void IConfigureLogging.Configure(IConfigureThisEndpoint specifier)
{
SetLoggingLibrary.Log4Net<RollingFileAppender>(null,
a =>
{
a.CountDirection = 1;
a.DatePattern = "yyyy-MM-dd";
a.RollingStyle = RollingFileAppender.RollingMode.Composite;
a.MaxFileSize = 1024 * 1024;
a.MaxSizeRollBackups = 10;
a.LockingModel = new FileAppender.MinimalLock();
a.StaticLogFileName = true;
a.File = "logfile";
a.AppendToFile = true;
});
if (GetStdHandle(STD_OUTPUT_HANDLE) == IntPtr.Zero)
return;
SetLoggingLibrary.Log4Net<ColoredConsoleAppender>(null,
a =>
{
LiteLoggingHandler.PrepareColors(a);
a.Threshold = Level.Info;
}
);
}
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(int nStdHandle);
const int STD_OUTPUT_HANDLE = -11;
}
A final note, I also had to set all of the properties of my saga data object as virtual, per standard NHibernate practice. This became very apparent once the system was actually using NHibernate.
public class ItemData : ISagaEntity
{
public virtual Guid Id { get; set; }
public virtual string Originator { get; set; }
public virtual string OriginalMessageId { get; set; }
}
This is a long explanation, but hopefully it'll help someone else out down the road. If anyone has suggestions on a better way to accomplish this, or the correct way to use profiles, please let me know!

WCF MesageContract - customizing outgoing SOAP message - multiple bodies

I have to call a Web service that is extremely demanding (unstandard) regarding the SOAP message format that it chooses to process. I have no control over the server side implementation and there is no WSDL available, all I have is an intercepted message attached bellow.
My first thought was WCF+MessageContract, but whatever I do with the last, I can't seem to get the right result. Outgoing messages should look like the one bellow. The most tricky part seems to be multiple body contents ("ProxyInfo" and "PayloadInfo" bellow). Besides that I also can not get WCF to remove "Action" element from SOAP message header. I realize that it is a vital element to WCF, but I doubt that I could persuade Web service to accept it. The reply will probably be another story, but I will cross that bridge when I get to it.
Currently I am considering custom serialization and post-/pre- processing of outgoing/incoming messages. In the worst case I guess I will have to do Web requests as well as serialization manually. Please help, I am getting realy desperate...
<?xml version="1.0" encoding="UTF-8" ?>
<e:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsse="http://docs.oasisopen.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<e:Header>
<ServiceHeader xmlns="http://services/serviceheader" e:actor="http://services/loadbalancer" >
<ServiceLevel>
<Type>HIGH</Type>
<Method>FIFO</Method>
</ServiceLevel>
</ServiceHeader>
</e:Header>
<e:Body>
<ProxyInfo xmlns="http://services/proxyinfo">
<Server>
<Address>proxy1:8080</Address>
<AppId>case_delegator</AppId>
</Server>
</ProxyInfo>
<PayloadInfo xmlns="http://services/payload">
<GetConfirmation>
<CaseId>
<Id>9728DFC889874CC8B1505D91E33FCFCD</Id>
</CaseId>
</GetConfirmation>
</PayloadInfo>
</e:Body>
</e:Envelope>
If you don't want to use Address header you have to use binding without WS-Addressing. In your case use BasicHttpBinding. It will not use WS-Addressing and Action SOAP header but instead it will use SOAPAction HTTP header.
For your message contract try to use something like this:
[DataContract]
public class ServiceHeader
{
...
}
[DataContract]
public class ProxyInfo
{
...
}
[DataContract]
public class PayloadInfo
{
...
}
[MessageContract(IsWrapped = false)]
public class Request
{
[MessageHeader(Namespace="http://services/serviceheader")]
public ServiceHeader ServiceHeader { get; set; }
[MessageBodyMember(Namespace="http://services/proxyinfo")]
public ProxyInfo ProxyInfo { get; set; }
[MessageBodyMember(Namespace="http://services/payload")]
public PayloadInfo PayloadInfo { get; set; }
}
The strange thing is the actor attribute in ServiceHeader. Your message doesn't define namespace for prefix e so the message is not valid XML.

How to create a WCF dead-letter service for MSMQ3.0

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.