Friday, March 22, 2013

WCF with MSMQ

I want to share how to use netMsmqBinding in WCF today. I need to create a solution which able to support asynchronous operation, which mean the WCF service is down but the client still able to make request. The client request will be kept in a queue in MSMQ, and then when the WCF service is back online, it will process whatever requests which are pending in the queue.

First, we need to configure MSMQ. But before that, we need to make sure MSMQ had already been installed. My operating system is Windows 2008 R2, here are the steps to check whether MSMQ had been installed, otherwise we need to install it.

1. Open up Server Manager.
2. Check whether you see Message Queuing is shown in the features list? If yes, skip to step 6.
3. Click the Add Features link button.
4. Check the Message Queuing checkbox.

5. Click the [Install] button. You may need to reboot your server.
6. After the installation is done, you will notice "Message Queuing" is appearing under the Features tree.
7. Proceed to collapse it and then try to create a new queue by right clicking the Private Queue, and then click the New -> Private Queue.
8. Give a name for your new queue and then click the [OK] button.
9. Right click the newly created queue, and then click the Properties.
10. If your server is not joined with any domain and it is running in WORKGROUP, you need to set the Privacy level to None. And, un-check the Authenticated box.


11. Then, go to Security tab, set Allow Full Control to Everyone. For better security control, it is recommended to grant Allow Full Control permission to the application pool identity account only (for example, IIS APPPOOL\AppPoolName) which is going to be used to host the WCF service.



Now, it is time to code your WCF service. After you are done with your coding, here are the web configuration that you need for netMsmqBinding. For WORKGROUP server, you need to set security mode, protection level as None.


<bindings>
  <netMsmqBinding>
    <binding name="basicMsmq" exactlyOnce="false" >
      <security mode="None">
        <transport msmqAuthenticationMode="None" msmqProtectionLevel="None"/>
      </security>
    </binding>
  </netMsmqBinding>
</bindings>


Then, for the service endpoint configuration, you need to set your queue name which you had created just now at the endpoint address:


<services>
  <service name="<YourServiceName>"
            behaviorConfiguration="<YourServiceBehavior>">

    <endpoint name="netMsmqServiceEndpoint"
              address="net.msmq://localhost/private/<YourQueueName>"
              binding="netMsmqBinding" bindingConfiguration="basicMsmq"
              contract="<YourServiceContractName>" />

    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>
</services>


When you are done, host your WCF service to IIS. Before that, you need to make sure IIS had been enabled with net.msmq binding. You can perform the following steps to check.

1. Open up IIS Manager.
2. Right click the Default Web Site (assume you are going to host your application in a virtual directory in default website).
3. Click the Edit Bindings... menu.
3. If you see net.msmq binding type is in the list, you skip to steps 6. Otherwise, click the [Add] button.
4. Select net.msmq type from the drop down list, and then enter localhost as binding information.

5. Click the [OK] button.
6. Now, create a new application in default website that host your WCF service.
7. Select the newly created application, and then open Advanced Settings.
8. At the Enabled Protocols properties, append net.msmq to the existing value with comma delimiter.
9. Click the [OK] button, and your application is enabled with MSMQ binding.

Before proceed for testing, need to make sure Net.Msmq Listener Adapter windows service is running.


Now, you can start testing your WCF service with a browser, go to the service url and try to get the WSDL. After tested everything works fine, you are good to go to create a WCF client application.

However, there are a few common errors that you may encounter during the service setup, but the given error message is actually not really meant for it.

Common Error 1:

An error occurred while opening the queue:Access is denied. (-1072824283, 0xc00e0025). The message cannot be sent or received from the queue. Ensure that MSMQ is installed and running. Also ensure that the queue is available to open with the required access mode and authorization.


Root Cause:
The IIS process worker has insufficient permission to read the queue.

Resolution:
You need to make sure the application pool identity account or everyone is given appropriate access.

Common Error 2:

An error occurred while opening the queue:This operation is not supported for Message Queuing installed in workgroup mode. (-1072824214, 0xc00e006a). The message cannot be sent or received from the queue. Ensure that MSMQ is installed and running. Also ensure that the queue is available to open with the required access mode and authorization.


Root Cause:
The service endpoint address is invalid.

Resolution:
Make sure the endpoint address is in the following format:
For example: net.msmq://localhost/private/<YourQueueName>


    <endpoint name="netMsmqServiceEndpoint"
              address="net.msmq://localhost/private/<YourQueueName>"
              binding="netMsmqBinding" bindingConfiguration="basicMsmq"
              contract="<YourServiceContractName>" />



Back for the testing, after you have created a service client and added the service reference to your WCF service host. Make a few requests first from your client to make sure the WCF service is working fine.
After that, you can purposely stop the IIS service for your WCF service, and then use your client to submit a few more requests. At this time, you should expect to see your client is still working fine and the queue is piling up with requests.



Tuesday, March 5, 2013

Performance Profiler in Visual Studio 2012

Today I want to share how to use the performance profiler tool which is available in Visual Studio 2012. I had been using 3rd party profiler tool such as Red Gate all these while, and you know that we have to pay some money for the license. Since Visual Studio 2012 comes with the performance profiler, we can save some money although I find the user friendliness of the tool is not as good as Red Gate's ANTS Performance Profiler.

Note: this tool only available in Visual Studio 2012 Premium and Ultimate edition.

A bit of intro about what is a performance profiler. It is a tool that monitor your running application and capture the information like the time of execution between individual line of codes. Besides, it also has the capability to capture objects in the memory, CPU utilization at that time or any resource contention (deadlock). With these information, it will be easy for us to identify which line of code is causing bottleneck, and the objects in the memory are really get collected by garbage collector or not, if not, it mean memory leak has occurred.



In your Visual Studio 2012, after clicking the Analyze menu, you can straight away start the performance profiler tool by clicking at the "Start Performance Analysis". It will run the profiler with default settings. After the profiler tool is started, it will fire up your application and begin profiling your application. Then, you can proceed to play around with your application. If you wish to track a certain area of code, you can just use your application in a way that you know how it would trigger that area of code, and then quit the application. The profiler tool will start its analysis job then provide the report later.

My experience is I have a web application to be profiled, but it is in layered architecture, means that I have multiple projects need to be profiled at the same time. The default profiler setting is not able to capture the information that I want. Therefore, I have to click the "Lauch Performance Wizard" menu to configure my profiler.


I have selected "Instrumentation" in order to capture the response time between lines of code.


Then, select the web project that I wish to profile. Here is the tricky part, by default it would select all the projects for you, and for the first time user like me, I would assume that it will profile everything for me even the selected class library projects. If your application architecture design is similar to mine, multiple class library projects are referenced by your web project, you can skip from selecting the class library projects in this window. Later, there is a place for you to select which assemblies (dll) to be instrumented together with your web project.



Next, "Enable Tier Interaction Profiling", the description look interesting, just enable it if your project is a web project.


Uncheck the checkbox, do not launch profiling yet because I have not add the assemblies to be instrumented together with my web project.

After clicking the Finish button, a new profiler session will be created in your Performance Explorer window. Right click the profiler session, then open the "Properties".


I would suggest to change the "Report Location" because when the first time I use this tool, all the reports are generated into my solution root folder, it look messy when getting more and more performance reports generated. Hence, I have a folder created call PerformanceReport in my solution folder to keep those performance reports. Then, click the Apply and OK button to close this window.




Now, back to Performance Explorer window, right click the Targets folder, then "Add Target Binary". Browse through your web project's bin folder, then select all the assemblies (dll) which are referenced by your project.


In order to start profiling, right click the Profile, then click the "Start Profiling" menu. You should expect to see your web project get built and default browser will be opened up for you automatically. Then, start to play around with your application. Once you are done with it, click the "Stop Profiling" or close the web browser.

Later, a performance report will be generated.


The graph is about the CPU utilization during the profiling, I personally do not find it useful.
The Hot Path is the suggested functions that you need to pay attention.
The Functions With Most Individual Work is the list of functions that take very long time to process in sorted order.

Play around with the views, there is a call tree view where display top to bottom of a function to another function call, the data is actually quite well self-explained. I personally find the "Avg Elapsed Exclusive Time" value is more useful which tell a particular function response time.


If you go to the modules view, you would find the screen like above. It tells you how times of your assemblies had been called, and I would normally do is to sort the Avg Elapsed Exclusive Time in descending order, and then double click the class.


Then, change the performance metric if you like. Click the function which show long elapsed time. At the bottom, you will see your code. It is the hint where you need to tune your code.

Enjoy your code tuning~

Monday, February 4, 2013

ASP.NET 4.0 - Request Validation

Today, I encounter an error: A potentially dangerous Request.QueryString value was detected from the client.

If you submit any HTTP request which contain XML string, it will be detected as a potential threat to the web application, the above message is to tell you that someone may intends to inject some cross site scripts to your web application. By default, the request validation is turned on automatically, the dangerous string will be truncated. However, due to some business requirements, somehow you want to make your application to accept XML string request. Therefore, you want to disable the request validation.

If you had experience in ASP.net 2.0, you know that you can simply disable the request validation by adding directive RequestValidation="false" to your aspx page. But, in ASP.net 4.0, there are something new. Even though you have added the directive, you still get the same warning message.

There is something extra need to be done for ASP.net 4.0. We need to specify <httpRuntime> as highlighted below in the web.config file. If you wish to disable the request validation for all the pages, you do not need to add directive to every individual page, instead, just use <pages> for all pages.


  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" requestValidationMode="2.0" />
    <pages validateRequest="false" />
  </system.web>


Wednesday, January 30, 2013

Debugging Problem with Visual Studio 2012 Unit Test

Today I found a very annoying problem while debugging my unit test with Visual Studio 2012. In a usual case scenario, when you are debugging your assembly code, at any breakpoint you can hit F10 or F11 to step over or step into the code line by line. However, today I find it behave differently, when I step over my code, the execution is skip jumping a few lines or more.

I would like to share the steps how I troubleshoot this problem and found the root cause and resolution.

First, check all your projects are not running in "Optimize Code" by opening up project properties and look for Build section then locate the "Optimize Code" checkbox is not checked.



Then, run your projects in debug mode, open up the Module window from the Debug menu, and then check all your assemblies are loaded and identify all the symbol paths are correct.


The loaded symbol paths look fishy. When you go to the project bin folder, you would notice that there are extra pdb files in the folder. For example:

<Assembly Name>.dll
<Assembly Name>.pdb
<Assembly Name>.instr.pdb

And then, in your Module window, it shows that the loaded symbols are actually <Assembly Name>.instr.pdb.

Well, when we enable Code Coverage in unit test, the instrumented assembly will be generated into another set of *.pdb files which are named as <Assembly Name>.instr.pdb. I never notice the *.instr.pdb would actually get loaded instead.

After disabling the Code Coverage, Test Impact, Intelli Trace, everything from my unit test setting, then do a solution cleaning and rebuild, no more *.instr.pdb file is generated. While debugging the code, only normal *.pdb files get loaded and no more code jumping around after hitting F10.

However, I am a little bit curious what is the actual root cause, so I go and enable back the Code Coverage. Surprisingly, *.instr.pdb files are not generated. So, I go and enable Test Impact, now I see *.instr.pdb files are generated, and I replicated the same problem occur earlier again.

So, is it a bug in Visual Studio 2012? :P



Sunday, January 20, 2013

How to Configure WCF Service Client to Consume 3rd Party Web Service via Secure Channel

One of the developers in my company faced a problem in consuming a 3rd party web service from her ASP.net web application. The web service is hosted in a secure channel. The vendor provided a self-signed SSL certificate. I would like to share how to configure our WCF client to connect to the 3rd party web service via HTTPS with the provided self-signed SSL certificate.

First, we need to import the provided cert into the local machine.
  1. Open Management Console (mmc.exe)
  2. Click File menu, then click at Add or Remove Snap-ins.
  3. Select Certificates from the list box then click the Add button.
  4. Select Computer Account then click Next button.
  5. Select Local Computer then click Finish button.
  6. Collapse the Certificates tree view, right click the Personal folder, then select All Tasks, then click at Import...
  7. Select Local Machine, then click Next button.
  8. Click the Browse button and locate the certificate which provided by the vendor.
  9. Place the certificate to the Personal Certificate Store, then click the Next button.
  10. Finally, click the Finish button.


Then, go to your Visual Studio, add a web service reference to your project first with the provided WSDL by the vendor. Then, you will be warned that the site's cert is not issued by a company that you have not chosen to trust. This is a normal warning when the vendor does not use a cert which provided by a Certificate Authority.


After adding the service reference, the configuration file will be added with binding configuration automatically.

Ensure the binding security mode is Transport, then client credential type is Certificate.


<bindings>
  <basicHttpBinding>
    <binding name="<Binding Name>">
      <security mode="Transport">
        <transport clientCredentialType="Certificate" />
      </security>
    </binding>
  </basicHttpBinding>
</bindings>

Then, create a binding behavior that locate your certificate.

<behaviors>
  <endpointBehaviors>
    <behavior name="CertificateBehavior">
      <clientCredentials>
        <clientCertificate storeLocation="LocalMachine"
                            storeName="My"
                            findValue="bc74ca0d37510e5e87773707b60cd0490653662f"
                            x509FindType="FindByThumbprint" />
        <serviceCertificate>
          <sslCertificateAuthentication certificateValidationMode="None"/>
        </serviceCertificate>
      </clientCredentials>
    </behavior>
  </endpointBehaviors
</behaviors>


There are a few ways to locate your certificate. I chose to find by thumbprint. How to locate the certificate thumb print? Go back to the Management Console and then double click the imported certificate. Go to the details tab, scroll down and locate the thumbprint field.


Copy and paste the thumbprint to your configuration file, and then remove all the spaces.

If you wish to find certificate by issuer name, you can refer to the value in the Issued By in the General tab. And then, set findValue="CN=<issuer name>".

Finally, set the endpoint behavior configuration.

<endpoint address="https://<webservice url>"
  binding="basicHttpBinding" bindingConfiguration="<binding name>"
  contract="<contract name>" name="<endpoint name>"
  behaviorConfiguration="CertificateBehavior" />

When you do a test run, you may encounter some common errors.

Error 1: Could not establish trust relationship for the SSL/TLS secure channel with authority
Root Cause: Due to self-signed certificate, the client cannot validate the certificate.
Resolution: Disable client SSL certificate authentication with the following endpoint behavior configuration.

<serviceCertificate>
  <sslCertificateAuthentication certificateValidationMode="None"/>
</serviceCertificate>


Error 2: Cannot FindByThumbprint - Invalid Hexadecimal String Format
Root Cause: Cannot locate the certificate. Either the certificate thumbprint is invalid, or the certificate was imported into different user store.
Resolution: If you run your web application by using Visual Studio Development Server, the hosting service is running under your current login account. You need to import the cert to your current user and set the correct certificate store in your config file. When you deploy your application to IIS, you need to make sure the IIS service account is imported with the correct cert.



Send Transactional SMS with API

This post cover how to send transactional SMS using the Alibaba Cloud Short Message Service API. Transactional SMS usually come with One Tim...