JQuery and WCF Working Hand-in-hand

November 27, 2010 § Leave a comment

JQuery and WCF Working Hand-in-hand

 

Introduction

In this article we will learn how to call a WCF service from JQuery. We will also be creating a sample web application for the demonstration purposes and we’ll explain the code as we go along.

The JQuery library can be downloaded from here. The version of JQuery that we are going to use is 1.4.2.min.

What’s the Advantage of Calling WCF From JQuery?

For readers who are not aware of JQuery here is a little lead in. JQuery is a JavaScript library which helps in traversing through the HTML elements on the webpage easier. For example you can access a TextBox with id txtName as $(‘#txtName’). Providing the effects and animations for the controls are also relatively simple when compared with the implementation using raw JavaScript.

Apart from the UI level operations it is also possible to call the WCF or WebServices using JQuery. Below are the advantages of calling WCF service from JQuery:

  1. You don’t have to post the request to the code behind since the client will directly call the WCF service.
  2. Page reload is avoided; hence it proves to be a performance optimized way.
  3. User experience will be smooth, since there won’t be any post back occurrence.
  4. Calling WCF using JQuery also gives the provision to perform callbacks for both success and error scenarios.

 

Creating a Sample Application

Let us create a sample application.

 

  1. As a first step create a blank solution and name it as JQueryAndWcfSolution.
  2. To the solution add a website with name DemoWebsite.
  3. Create a folder under the website named Script. Add the JQuery library to it.

 

Creating the WCF Service

Add AJAX Enabled WCF service to WebSite naming BankingService.svc. Go to theBankingService.cs file and add a method called Deposit.

Below is the code:

 

  [ServiceContract(Namespace = "")]
  [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
  public class BankingService
  {
      [OperationContract]
      [WebInvoke(Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]    
      public string Deposit(string accountId, string firstName, string lastName, string amount)
      {
          return string.Format("Mr. {0} {1}, Sum of {2} USD has been deposited to your account {3}", firstName, lastName, amount, accountId);
      }
  }

 

Note that the Deposit method is decorated with the attribute WebInvoke. This attribute is required in order to invoke this method from JQuery.

WebInvoke attribute is supplied with three properties.

 

  1. Method: WCF service can be called from JQuery through GET, POST, PUT or DELETEmethod. The method value provided in the attribute should be the same with the one provided in the JQuery code.
  2. BodyStyle: This allows the developer to mention whether the request should be wrapped, response should be wrapped, both should be wrapped or nothing should be wrapped.
  3. ResponseFormat: Supported response formats are JSON and XML.

 

In our demo application we will use GET method, NoWrapping (WebMessageBodyStyle.Bare) and response format as JSON.

WCF Configuration Entries in Web.Config

A crucial part while creating a WCF service is configuring the System.ServiceModel tag in theweb.config file. Below is the configuration entry for our WCF BankingService.

 

  <system.serviceModel>
  		<behaviors>
  			<serviceBehaviors>
  				<behavior name="BankingServiceAspNetAjaxBehavior">
  					<serviceMetadata httpGetEnabled="true" />
  					<serviceDebug includeExceptionDetailInFaults="true" />
  				</behavior>
  			</serviceBehaviors>
  			<endpointBehaviors>
  				<behavior name="BankingServiceAspNetAjaxBehavior">
  					<webHttp/>
  				</behavior>
  			</endpointBehaviors>
  		</behaviors>
  		<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
  		<services>
  			<service name="BankingService">
  				<endpoint address="" behaviorConfiguration="BankingServiceAspNetAjaxBehavior"
  				 binding="webHttpBinding" contract="BankingService" />
  			</service>
  		</services>
  </system.serviceModel>

 

In the above configuration note that the binding used is webHttpBinding. It is also important to set thehttpGetEnabled and includeExceptionDetailInFaults attributes in the behaviour to true.

 

Webpage and JQuery Code

Let us create the webpage and name it BankDeposit.aspx. Below is the HTML:

 

  <body>
      <form id="frmBanker" runat="server">
      <div>
          <table style="width: 506px">
              <tr>
                  <td>
                      Account Number:
                  </td>
                  <td>
                      <input id="txtAccountId" type="text" />
                  </td>
              </tr>
              <tr>
                  <td>
                      First Name:
                  </td>
                  <td>
                      <input id="txtFirstName" type="text" />
                  </td>
              </tr>
              <tr>
                  <td>
                      Last Name:
                  </td>
                  <td>
                      <input id="txtLastName" type="text" />
                  </td>
              </tr>
              <tr>
                  <td>
                      Amount:
                  </td>
                  <td>
                      <input id="txtAmount" type="text" />
                      <b>(USD)</b>
                  </td>
              </tr>
              <tr>
                  <td>
                  </td>
                  <td>
                      <input id="btnDeposit" type="button" value="Deposit" />
                  </td>
              </tr>
          </table>
      </div>
      </form>
  </body>

 

Below is the JQuery code on the webpage:

       <script src="Script/jquery-1.4.2.min.js" type="text/javascript"></script>
       <script type="text/javascript">
           $(document).ready(function() {
               $('#btnDeposit').click(function(event) {
                   event.preventDefault();
                   var parameters = '{"accountId:"' + $('#txtAccountId').val() + '","firstName":"' + $('#txtFirstName').val() + '","lastName":"'
                               + $('#txtLastName').val() + '","amount":"' + $('#txtAmount').val() + '"}';
                   $.ajax({
                       type: "GET",
                       url: "http://localhost/DemoWebsite/WCF%20Service/BankingService.svc/Deposit",
                       data: parameters,
                       contentType: "application/json; charset=utf-8",
                       dataType: "json",
                       processdata: true,
                       success: function(result) {
                           alert(result);
                       },
                       error: function(error) {
                           alert("Error occured while calling the Banking Service!");
                       }
                   });
               });
           });
       </script>

 

The above JQuery function will be invoked when the button btnDeposit is clicked. You will notice a number of properties being set in the JQuery click event handler code. Lets look at this step by step.

 

  1. Type: Type of method used to post the request. This could be GET, POST, PUT or DELETE.
  2. Url: The URL of the WCF Service. You could also provide the relative path if the service lies under the same website. The name of the method to be invoked should be appended to the URL as http://localhost/DemoWebsite/WCF%20Service/BankingService.svc/Deposit.
  3. Data: Parameter values that have to be passed to the WCF service method. The data has to be formatted as “{‘param1′:’value1’, ‘param2′:’value2’}”
  4. ContentType: Type of the content that will be sent to the server.
  5. DataType: Type of data that will be sent to the server.
  6. Success: This function will get executed if the service call and execution of the service method is successful. The return value of the service method will be passed to the success callback function.
  7. Error: This function will get executed if the service call fails or any exception is thrown. The error details will be passed to the error callback function.

 

Conclusion

I hope this article gives you a better understanding of calling WCF services from JQuery, while establishing the supremacy of the combination. If you have any queries please make use of the comments section.

 

Advertisements

Changes in System.IO classes in .NET Framework 4.0

November 25, 2010 § Leave a comment

Introduction

Earlier versions of .NET Framework (prior to .NET Framework 4.0 and going back to .NET 2.0) had many APIs in the System.IO namespace for enumerating lines in a file, enumerating files in a directory, etc. These APIs returned arrays which could then be looped over to process each item.

For example, if one desires to print all the lines in a file, he/she can use theFile.ReadAllLines API to get an array of strings (each string representing a line) which can then be printed by iterating over the array.

  string[] allLines = File.ReadAllLines("foo.txt");
  foreach(string line in allLines)
  {
  	Console.WriteLine(line);
  }

Similarly, to get a list of all files/directories in a directory, you call the GetFiles/GetDirectories API on DirectoryInfo class.

  DirectoryInfo dirInfo = new DirectoryInfo(@"c: \windows\system32");
  FileInfo[] arrayFileInfo = dirInfo.GetFiles();
  DirectoryInfo[] arrayDirectoryInfo = dirInfo.GetDirectories();

Issues With the Old APIs

While the above APIs worked as expected, there was a considerable performance hit when they were exercised on large files. The performance hit is coming from the fact that the APIs mentioned above are synchronous. i.e. The operation is blocked until all the lines in a file are read (to populate the array). Imagine the time the operation will take when you are parsing a 1 GB log file. Another issue on a memory-constrained execution environment will be the amount of memory needed to allocate the array. If you were only interested in the first few lines, you still have to pay the penalty of loading all the lines in memory.

New APIs in .NET Framework 4.0

To overcome these issues, in .NET Framework 4.0, the Base Class Library folks over at the Common Language Runtime team built new APIs with enumerators rather than arrays. These new APIs were extremely efficient because they didn’t read all the lines into memory at once. Also since it read only one line at a time into memory, you can abrupt your iteration at any point without having to pay the late-comers tax we saw in the older APIs.

The new APIs are:

  • File.ReadLines (+1 overload)
  • File.WriteAllLines (+1 overload)
  • File.AppendAllLines (+1 overload)
  • DirectoryInfo,EnumerateDirectories(+2 overloads)
  • DirectoryInfo,EnumerateFiles (+2 overloads)
  • DirectoryInfo.EnumerateFileSystemInfos(+2 overloads)
  • Directory.EnumerateDirectories (+2 overloads)
  • Directory.EnumerateFiles (+2 overloads)
  • Directory.EnumerateFileSystemEntries (+2 overloads)

These new work by returning an IEnumerable <t> which is a much more performant operation than an array of objects returned by the earlier methods.

The application developer can use the returned iterator to iterate, reducing the startup disk I/O experienced in the older APIs.

Hands On

Here is how the APIs can be used:

  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.IO;

  namespace FileEnumerators
  {
      class Program
      {
          static void Main(string[] args)
          {
              DateTimeOffset tstart = new DateTimeOffset(DateTime.Now);

              string[] oldlines = File.ReadAllLines(Environment.ExpandEnvironmentVariables(@"%TEMP%\registry.reg"));

              DateTimeOffset tstop = new DateTimeOffset(DateTime.Now);
              TimeSpan difference = tstop - tstart;
              Console.WriteLine("Time taken with old API = " + difference.ToString());
              tstart = new DateTimeOffset(DateTime.Now);
              for (int i = 0; i < oldlines.Length; i++)
              {
                  // Dont do anything. Just cycle through
              }

              tstop = new DateTimeOffset(DateTime.Now);
              TimeSpan cycleDifference = tstop - tstart;
              Console.WriteLine("Cycle time taken with old API = " + cycleDifference.ToString());

              tstart = new DateTimeOffset(DateTime.Now);
              IEnumerable<string> allLines = File.ReadLines(Environment.ExpandEnvironmentVariables("%TEMP%\\registry.reg"));
              tstop = new DateTimeOffset(DateTime.Now);
              difference = tstop - tstart;
              Console.WriteLine("Time taken with new API = " + difference.ToString());
              tstart = new DateTimeOffset(DateTime.Now);
              foreach (string str in allLines)
              {
                  // Dont do anything. Just cycle through
              }
              tstop = new DateTimeOffset(DateTime.Now);
              cycleDifference = tstop - tstart;
              Console.WriteLine("Cycle time taken with new API = " + cycleDifference.ToString());
          }
      }
  }

The results are very obvious. On my system (currently already pegging one of the two CPUs on a dual-core at constant value), I exported my registry to a temp file and ran the above code on that file. On a DEBUG build, the results are below:

Time taken with old API = 00:00:11.6660156
Cycle time taken with old API = 00:00:00.0087891
Time taken with new API = 00:00:00
Cycle time taken with new API = 00:00:09.9238281

The new API (which has the enumerators) does not block to read all the contents of a large file. Instead it immediately returns the enumerator (highly performant). The old API loads everything in memory so it takes an initial hit, however its cycle time is almost zero since it does not have to hit the hard drive to get the values of the strings again.

Usage of the Performant APIs

The new APIs can be very useful when you want to list all files/directories in a directory which has a lot of content including lot of sub-directories.

The new APIs can also be used where we want to read lines in a very large text file.

Summary

In the above article, we saw how the new APIs in System.IO help improve the performance by using enumerators, hence reducing the initial lookup time

Having a Second Thoughts on Windows Phone 7 Development

November 22, 2010 § Leave a comment

Introducing XPF – A Layout Framework for XNA

 

We’re very proud to announce the public beta of XPF – a layout framework for XNA on Windows & Windows Phone 7.  For too long performing 2D layouts in XNA has been an arduous task, the simplest of layouts often produces verbose and inelegant code.  If you’ve come from a WPF/Silverlight background, where fluid and logical layouts are second nature, the inability to combine XNA with WPF and/or Silverlight only compounds the frustration.  With XPF, Red Badger is addressing this problem.

Familiar Development Experience

XPF has been specifically designed to be familiar to WPF & Silverlight developers and comes with a collection of out of the box controls, that can be composed together to create flexible layouts in no time at all.  The beta launches with the following controls:

  • Border
  • Button
  • ContentControl
  • Grid
  • Image
  • ItemsControl
  • RootElement (similar to Window)
  • ScrollViewer
  • ScrollContentPresenter
  • StackPanel
  • TextBlock

XPF also supports Dependency Properties, Attached Properties, Animation (currently WP7 only) and Data Binding (one and two-way).

Pure XNA

XPF is designed to run in a pure XNA application, it doesn’t host XNA inside a WPF or Silverlight application.  All the controls have been written from the ground-up to work in XNA 4.0 and fit into XNA’s Update & Draw game loop.

Extensible

XPF has been designed to be modular and extensible in two key ways.  Firstly, creating custom controls to use alongside the controls you get out of the box is easy.  If you’ve ever created a custom control in WPF or Silverlight, using the 2 phase measure and arrange layout system, then XPF gives an almost identical experience.

Secondly, the integration point between XPF and your XNA application has been designed to be extremely flexible.  XPF doesn’t really know anything about XNA, it’s written entirely around agnostic interfaces – so whilst XPF comes with a renderer that you can use out the box, should you want to create your own, or integrate to an existing engine, you simply have to satisfy a few core interfaces.

Try It

As XPF reaches completion we’re looking for early adopters, testers and feedback.  Nightly buildsof XPF for Windows and Windows Phone 7 are now available for you to try.  Download a build and read the Getting Started blog now!

 

VALIDATEINPUTATTRIBUTE CHANGES IN MVC3

November 8, 2010 § Leave a comment

VALIDATEINPUTATTRIBUTE CHANGES IN MVC3

The ValidateInputAttribute has received a nice little tweak in MVC 3 offering more fine grained control over parameters of a request.

In MVC 2 using ValidateInputAttribute was limited to the request level, that is all parameters in the request where either validated or not.  Lets demonstrate this with a simple example – a simple forum posting page,

<%@ Page Language=”C#” MasterPageFile=”~/Views/Shared/Site.Master” Inherits=”System.Web.Mvc.ViewPage<Common.Model.ForumPost>” %>
<asp:Content ContentPlaceHolderID=”TitleContent” runat=”server”>
Login
</asp:Content>
<asp:Content ContentPlaceHolderID=”MainContent” runat=”server”>
<h2>Post Question</h2>
<% using (Html.BeginForm()) { %>
<p>
<%=Html.LabelFor(c => c.Subject)%>
<%=Html.TextBoxFor(c => c.Subject)%>
</p>
<p>
<%=Html.LabelFor(c => c.Body)%>
<%=Html.TextAreaFor(c => c.Body)%>
</p>
<input type=”submit” value=”Post” />
<%} %>
</asp:Content>

We don;t care what the controller actions actually do but lets describe them here anyway

public class HomeController : Controller
{
    public ActionResult Post()
    {
        return View();
    }
[HttpPost]
    public ActionResult Post(ForumPost post)
    {
        return View();
    }
}

Now attempting to post any sort of markup back to the action will result in an exception being thrown,

If we wanted to allow markup to go through we can add the [ValidateInput(false)] attribute to the action.  The only problem with that is if we only wanted to allow markup in the Body and not the Subject we would have to write our own tests in the controller to prevent this.  Not the most ideal or clean solution.

MVC 3 solves this quite simply by extending the ValidateInputAttribute and allowing use to specify exclusions.  This means we can have validation turned on but specifically state the we don’t want to validate a specific request parameter(s) (e.g. Body).

[ValidateInput(true, Exclude = "Body")]

A very minor tweak that makes a big leap to being able to produce cleaner more readable code.

Sending E-Mail from SQL 2008 Express

November 5, 2010 § Leave a comment

Sending E-Mail from SQL 2008 Express

By Andrew Prisk, 2010/11/04

Wait…what? We all know that sending E-Mail from SQL 2008 Express is not possible without a third party component, right? Wrong. It is a common problem that most of us face while trying to build various lightweight applications. We wire them up to SQL Server Express and then we are not able to send email. However, there is an answer.

This solution is not entirely new, in fact there is an article that describes a very basic approach to this and can be found here:http://www.mssqltips.com/tip.asp?tip=1795. The solution works for simple use cases, but didn’t do everything I needed it to, so I went ahead and added to it.

For those of you not familiar with using the Common Language Runtime (CLR), it is basically a way in which to execute, or call, managed code written in C# or VB.NET from within the SQL Server environment. This is basic functionality that is bundled in all versions of SQL (from 2005 on), including Express. There are two parts to this solution:

  1. The source VB file.
  2. A SQL Script for: Configuring CLR, Loading the assembly and Creating the Stored Procedure

Let’s have a look at the vb source:

Import the appropriate namespaces

Imports System.Net 
Imports System.Net.Mail

We’ll call this SQLCLREmail – this will be very important later on.

Public Class SQLCLREmail 
 <Microsoft.SqlServer.Server.SqlProcedure()> _

No surprises here, just setting up a basic sub procedure, only we are accepting arguments that correspond as stored procedure variables…

 Public Shared Sub SendEmail(ByVal recipients As String _
      , ByVal CC as String _
      , ByVal BCC as String _
      , ByVal subject As String _
      , ByVal from As String _
      , ByVal body As String _
      , ByVal strAttachments as String _
      , ByVal strSMTPServer as String _
      , ByVal strSMTPServerPort as String _
      , ByVal strSMTPServerUser as String _
      , ByVal strSMTPServerPwd as String) 

        Using MailMsg As New MailMessage() 

        MailMsg.From = New MailAddress(from)
        MailMsg.Subject = subject 
        MailMsg.Body = body 
        MailMsg.IsBodyHtml = True

Gotcha number one, two, three and four; in order to send to multiple mail recipients (CC, BCC and attachments too),
they have to be passed in as one long string and then looped through and added individually

        If Not recipients.Equals(String.Empty) Then 
           Dim strRecip As String 
           Dim strTo() As String = recipients.Split(";") 
           For Each strRecip In strTo 
               MailMsg.To.Add(New MailAddress(strRecip)) 
           Next 
        End If

        If Not CC.Equals(String.Empty) Then 
           Dim strCCRecip As String 
           Dim strCCTo() As String = CC.Split(";") 
           For Each strCCRecip In strCCTo 
               MailMsg.CC.Add(New MailAddress(strCCRecip)) 
           Next 
        End If

        If Not BCC.Equals(String.Empty) Then 
           Dim strBCCRecip As String 
           Dim strBCCTo() As String = BCC.Split(";") 
           For Each strBCCRecip In strBCCTo 
               MailMsg.BCC.Add(New MailAddress(strBCCRecip)) 
           Next 
         End If

        If Not strAttachments.Equals(String.Empty) Then 
           Dim strFile As String 
           Dim strAttach() As String = strAttachments.Split(";") 
           For Each strFile In strAttach 
               MailMsg.Attachments.Add(New Net.Mail.Attachment(strFile.Trim())) 
           Next 
        End If

I added this purely for my own convenience, but it certainly enhances the assembly. If a custom SMTP server is passed, this will also check for custom credentials and a custom port. Otherwise it will assume that the local server is also the SMTP server using port 25.

        If Not strSMTPServer.Equals(String.Empty) Then 
           Dim smtp As New System.Net.Mail.SmtpClient 
           With smtp 
              If Not strSMTPServerUser.Equals(String.Empty) Then
                .UseDefaultCredentials = False 
                .Credentials = New System.Net.NetworkCredential(strSMTPServerUser, strSMTPServerPwd)
              End If
                .Host = strSMTPServer 
                .Port = strSMTPServerPort 
                .Send(MailMsg) 
           End With 
        Else
           Dim smtp As New System.Net.Mail.SmtpClient
           With smtp
                .Host = "localhost"
                .Port = 25 
                .Send(MailMsg) 
           End With
        End If
      End Using 
    End Sub 
End Class

That’s it. Now all we have to do is compile it for use in SQL. To do that, open a command prompt (Start -> Run -> CMD) and type the following:

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\vbc /target:library C:\SQL_CLR\SendEmail.vb
Obviously, this snippet is making some assumptions, so change the paths accordingly for your system. After that, voila! In the same directory as the VB source file, there will be a newly minted DLL, ready to be loaded into SQL.

The second part of this is to deploy the DLL to the SQL Server environment and load it as an assembly, thereby making it available for our stored procedure. In order to do that, the first step is to configure CLR in SQL:

-- In the event you want to see all of the various 
-- advanced options that can be set, just execute 
-- sp_configure *after* 'show advanced options' has 
-- been set to 1
exec sp_configure 'show advanced options',1
reconfigure
GO
-- This simply enables CLR in the SQL environment
exec sp_configure 'clr enabled',1
reconfigure
go
-- If this is to be executed on a USER database, 
-- run this statement
alter database YourDatabase set trustworthy on
go
-- In the event this is a USER database and is 
-- owned by the user, run this to change it back to 'sa'
--ALTER AUTHORIZATION ON DATABASE::YourDatabase TO sa
go
use YourDatabase
go
-- Now we load the assembly in the specified database.
-- Make sure the path to the DLL is correct.
create assembly SendEmail from 'C:\SQL_CLR\SendEmail.dll'
with permission_set = external_access
GO

The second script will create the stored procedure that will call the CLR proc and pass in our values:

CREATE PROCEDURE [dbo].[p_SendEMail] 
 @recipients [nvarchar](4000), 
 @CC [nvarchar](4000),
 @BCC [nvarchar](4000),
 @subject [nvarchar](4000), 
 @from [nvarchar](4000), 
 @body [nvarchar](4000),
 @strAttachments [nvarchar](4000),
 @strSMTPServer [nvarchar](300), 
 @strSMTPServerPort [nvarchar](10),
 @strSMTPServerUser [nvarchar](300), 
 @strSMTPServerPwd [nvarchar](300)
WITH EXECUTE AS CALLER 
AS 
EXTERNAL NAME [SendEmail].[SQLCLREmail].[SendEmail]

Pretty straightforward – notice the naming convention used for the external name. Look familiar? It is the DLL name + class name + CLR proc name. Now for calling the proc:

EXEC p_SendEMail @recipients = 'user1@company.com'
 , @CC = 'user2@company.com'
 , @BCC = 'user3@company.com'
 , @subject = 'RE: Email from SQL Express'
 , @from = 'Test@SQLExpress.com'
 , @body = 'This is a test email from SQL Server' 
 , @strAttachments = 'C:\test1.txt;C:\test2.txt'
 , @strSMTPServer = 'my.smtpserver.com'
 , @strSMTPServer = '25'
 , @strSMTPServerUser = ''
 , @strSMTPServerPwd = ''

That’s it – if the SMTP information is correct, the mail should be on its way.

So in wrapping up there are additional features that you may need to build in to suit your environment. These include: Logging and Error Handing (SQL TRY/CATCH block would work well). It is also important to note that this has been successfully tested and deployed in both SQL Express 2008 and SQL Express 2008 R2; it may very well work with SQL Express 2005, but it will depend greatly upon the version of the .NET framework that is installed on the server.

Resources:

SendEmail.vbCLR Setup.sqlp_SendEMail.sql

 

Where Am I?

You are currently viewing the archives for November, 2010 at Naik Vinay.