EziData Solutions

Web, NET and SQL Server

Adding multiple parameters to JSON-enabled WCF service

One thing you’ll be tempted to do when you first start creating web services is to add multiple parameters to your web methods. Don’t, it will soon trip you up, especially if any of those parameters are complex types.

A better way to handle calling WCF web services that return JSON formatted results is to use Request and Response objects. Your WCF service accepts a single complex Request object that contains all the values it needs to perform its job. The results, along with any exceptions and messages are passed back to the caller in the Response object.

In this post, we’ll modify our GetPlaces method to use Request and Response objects instead of querystring parameters.

First add the following PlaceRequest and PlaceResponse classes.

Code Snippet
  1. public class PlaceRequest
  2. {
  3.     public string Country { get; set; }
  4.     public int MaxPopulation { get; set; }
  5. }

 

Code Snippet
  1. public class PlaceResponse
  2. {
  3.     public bool HasError { get; set; }
  4.     public string Status { get; set; }
  5.     public List<Place> Results { get; set; }
  6. }

Then modify the GetPlace method as follows.

Code Snippet
  1. [OperationContract]
  2.         [WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json)]
  3.         public PlaceResponse GetPlaces(PlaceRequest Request)
  4.         {
  5.             // instantiate our response object
  6.             PlaceResponse response = new PlaceResponse();
  7.  
  8.             // create a list of places
  9.             List<Place> places = new List<Place>();
  10.  
  11.             places.Add(new Place {
  12.                 Name = "London",
  13.                 Country = "UK",
  14.                 Population = 7825200
  15.             });
  16.  
  17.             places.Add(new Place {
  18.                 Name = "New York",
  19.                 Country = "USA",
  20.                 Population = 8175133
  21.             });
  22.  
  23.             places.Add(new Place
  24.             {
  25.                 Name = "Los Angeles",
  26.                 Country = "USA",
  27.                 Population = 3862839
  28.             });
  29.  
  30.             places.Add(new Place {
  31.                 Name = "Sydney",
  32.                 Country = "Australia",
  33.                 Population = 4391674
  34.             });
  35.  
  36.             var results = from p in places
  37.                           where p.Country == Request.Country && p.Population < Request.MaxPopulation
  38.                           select p;
  39.  
  40.             response.Results = results.ToList();
  41.  
  42.             // return the response
  43.             return response;
  44.         }

You’ll notice that we’ve changed the WebGet tag to WebInvoke. This declaration enables us to use the HTTP POST verb, instead of GET, since the calling function will be sending a complex object in the request body, not just a parameter in the URL. 

To test this web service you’ll need to create a POST HTTP request. The easiest way to do this is use a tool such as Fiddler to create the request.

Add Content-Type:application/json to the request header and specify the body as such:

{"Request":{"Country":"USA", "MaxPopulation":"4000000"}}

You’ll notice the values for Country and MaxPopulation are enclosed in an object called Request. This is because the web method parameter is called Request.

If everything goes well, Fiddler will report a response that includes the following JSON.

{"HasError":false,"Results":[{"Country":"USA","Name":"Los Angeles","Population":3862839}],"Status":null}
Posted: Feb 15 2012, 17:41 by CameronM | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: ASP.NET | C#

Adding Parameters to JSON-enabled WCF service

In the previous post we looked at how you configure a WCF web service to return JSON-formatted results. In this post we’ll look at how you can handle methods that need parameters.

We’re going to add a parameter to our GetPlaces method that will be used to filter the results based on the Country property. 

Code Snippet
  1.     [OperationContract]
  2.     [WebGet(ResponseFormat = WebMessageFormat.Json)]
  3.     public List<Place> GetPlaces(string Country)
  4.     {
  5.         // create a list of places
  6.         List<Place> places = new List<Place>();
  7.  
  8.         places.Add(new Place {
  9.             Name = "London",
  10.             Country = "UK",
  11.             Population = 7825200
  12.         });
  13.  
  14.         places.Add(new Place {
  15.             Name = "New York",
  16.             Country = "USA",
  17.             Population = 8175133
  18.         });
  19.  
  20.         places.Add(new Place {
  21.             Name = "Sydney",
  22.             Country = "Australia",
  23.             Population = 4391674
  24.         });
  25.  
  26.         var results = from p in places
  27.                       where p.Country == Country
  28.                       select p;
  29.  
  30.         // return the list of places
  31.         return results.ToList();
  32.     }
  33. }

Run the web service in the browser and add the parameter name and value as below:

http://localhost:57128/PlaceService.svc/GetPlaces?Country=USA

The response will be the filtered array of Place objects matching the parameter (New York).

[{"Country":"USA","Name":"New York","Population":8175133}]


Posted: Feb 14 2012, 03:21 by CameronM | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: ASP.NET

Return JSON from WCF Web Service

JSON is a popular, light-weight method of formatting data destined for mobile devices. Many popular APIs default to JSON formatted responses, so it’s a good practice to follow.

If you are retrofitting existing WCF web services to return JSON it easy on paper, but can be painful in practice. In this post, we’ll add a JSON friendly WCF service to an existing web application and point out some of the gotchas that can make your life hell.

Firstly, add an AJAX enabled web service to your ASP.NET web application. Visual Studio will add a default web method and make a number of changes to your web config. We’re going to create a method the will return some information about places around the world, so call the web service PlaceService.

Create a simple class to represent the places, this should be in a separate cs file, but for ease of use, I’m adding it after the closing tag of our PlaceService.

Code Snippet
  1. public class Place
  2. {
  3.     public string Name { get; set; }
  4.     public string Country { get; set; }
  5.     public int Population { get; set; }
  6. }

Delete the existing DoWork method and replace it with this code GetPlaces. 

Code Snippet
  1. [ServiceContract(Namespace = "")]
  2. [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
  3. public class PlaceService
  4. {
  5.     [OperationContract]
  6.     [WebGet(ResponseFormat = WebMessageFormat.Json)]
  7.     public List<Place> GetPlaces()
  8.     {
  9.         // create a list of places
  10.         List<Place> places = new List<Place>();
  11.  
  12.         places.Add(new Place {
  13.             Name = "London",
  14.             Country = "UK",
  15.             Population = 7825200
  16.         });
  17.  
  18.         places.Add(new Place {
  19.             Name = "New York",
  20.             Country = "USA",
  21.             Population = 8175133
  22.         });
  23.  
  24.         places.Add(new Place {
  25.             Name = "Sydney",
  26.             Country = "Australia",
  27.             Population = 4391674
  28.         });
  29.  
  30.  
  31.         // return the list of places
  32.         return places;
  33.     }
  34.  
  35. }

View the page in the web browser and add the name of the method to the URL like so: http://localhost:57128/PlaceService.svc/GetPlaces 

Depending on what browser you use, you’ll either be prompted to download the JSON document, or the browser will display the JSON  directly.

{"d":[{"__type":"Place:#FileAccess.Web","Country":"UK","Name":"London","Population":7825200},{"__type":"Place:#FileAccess.Web","Country":"USA","Name":"New York","Population":8175133},{"__type":"Place:#FileAccess.Web","Country":"Australia","Name":"Sydney","Population":4391674}]}

 

Getting rid of the “d”

Our results are certainly JSON formatted but you’ll notice that they are wrapped in an object called “d”, short for data. Ideally, we want to get rid of the d and simply return an array of Place objects. This is done by modifying the web.config.

Sometimes it seems like configuring your web.config is a dark art, known only to a few souls. Thankfully, this change if pretty easy as all we need to do if modify the endpoint behaviour Visual Studio created for us. Look for the PlaceServiceAspNetAjaxBehavior and insert a tag to enable web HTTP. The modified config will look something like this (your namespace will be different).

Code Snippet
  1. <endpointBehaviors>
  2.   <behavior name="MyWebApplication.PlaceServiceAspNetAjaxBehavior">
  3.     <enableWebScript />
  4.     <webHttp />
  5.   </behavior>
  6. </endpointBehaviors>

Run the web service again and this time we’ll have a better response.

[{"Country":"UK","Name":"London","Population":7825200},{"Country":"USA","Name":"New York","Population":8175133},{"Country":"Australia","Name":"Sydney","Population":4391674}]   


Posted: Feb 12 2012, 01:03 by CameronM | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: ASP.NET

Building a Windows Phone 7 Look-a-like

After viewing some of the fan-mail for Sahas Katta's WP7 resume, I decided to check out just how hard it would be to build a WP7/Metro inspired website. While both Sahas' and my own attempts are not exactly perfect mirrors of the Windows Phone 7 end-user experience, it was certainly an interesting experiment.

Has your boss already bought you an Android? Are you stuck with an iPhone? Do you really wish you could experience a Windows Phone without parting with your hard-earned cash?

Well here is your solution. Take a look at this Windows Phone 7 (Mango-release) inspired site .

The site is constructed using some screenshots from the WP7 emulator and the layout is true to the actual device - trust me, I have spent enough time developing for WP7 that I know these proportions off-by-heart.

 

WP7 Inspired Site

Posted: Sep 13 2011, 07:26 by CameronM | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: ASP.NET | C# | WP7

Using the Bing Maps API

As part of developing a community directory website I needed to migrate a large number of Name/Address records from several existing systems. These records contained the usual street and suburb fields, but lacked Latitude and Longitude values.

Instead of doing the geocoding when the record is displayed in the map, I decided to utilise the Bing Maps API to perform the geooding of these addresses and store the resulting Latitude and Longitude in the database.

To perform the geocoding I used the Geocode Service, which is part of Bing Maps SOAP Services. According to their website

Microsoft® Bing Maps SOAP Services is a set of programmable SOAP services that allow you to match addresses to the map, search for points of interest, integrate maps and imagery, return driving directions, and incorporate other location intelligence into your Web application.

The first step is to sign up for your Bing Maps API key – it's free and painless, especially if you have a Windows Live account already.

Our Address Class

As this project was dealing with the names and addresses of organisations, I created a simple class to store the Organisation details and another to store the Addresses where the organisation operated. The important parts of the OrganisationAddress class are shown below.

public class OrganisationAddress

{

    public string StreetAddress { get; set; }

    public double Latitude { get; set; }

    public double Longitude { get; set; }

}

As each new OrganisationAddress was created, I called a function that passed the address to the Geocode Service and returned the Lat and Long, which I then saved with the OrganisationAddress.

 

To get started, add a Service Reference named MyBingMap to your Visual Studio project. The Uri to the GeocodeService is http://dev.virtualearth.net/webservices/v1/geocodeservice/geocodeservice.svc?wsdl

Once you have the service reference, you can create a function that send the street address (consisting of the house number, street name and suburb) and as a GeocodeRequest object to the Bing Maps API. The snipet below shows part of the function that sends in our OrganisationAddress object that contains that StreetAddress property.

    //instantiate a GeocodeRequest and pass in your Bing Maps API key

    MyBingMap.GeocodeRequest map = new MyBingMap.GeocodeRequest();

    map.Credentials = new MyBingMap.Credentials();

    map.Credentials.ApplicationId = "Your API Key";

 

    //add the address components to the GeocodeRequest.Query

    map.Query = OrganisationAddress.StreetAddress;

 

    //the Confidence level controls how accurate you want the results

    //if your address is good then Confidence.High should return the location

    //but be warned, if the location can not be found you'll get lat,long of 0,0

    MyBingMap.ConfidenceFilter[] filters = new MyBingMap.ConfidenceFilter[1];

    filters[0] = new MyBingMap.ConfidenceFilter();

    filters[0].MinimumConfidence = MyBingMap.Confidence.High;

 

    //add the assigned ConfidenceFilter to the Options

    MyBingMap.GeocodeOptions options = new MyBingMap.GeocodeOptions();

    options.Filters = filters;

    map.Options = options;

 

    //instantiate a GeocodeResponse for the service passing in your GeocodeRequest

    MyBingMap.GeocodeServiceClient geoClient = new MyBingMap.GeocodeServiceClient("BasicHttpBinding_IGeocodeService");

    MyBingMap.GeocodeResponse geocodeResponse = geoClient.Geocode(map);

 

    //if we get a response back, then save the Lat/Long with our OrganisationAddress

    if (geocodeResponse.Results.Length > 0)

    {

        if (geocodeResponse.Results[0].Locations.Length > 0)

        {

            OrganisationAddress.Latitude = geocodeResponse.Results[0].Locations[0].Latitude;

            OrganisationAddress.Longitude = geocodeResponse.Results[0].Locations[0].Longitude;

        }

    }

If like me you get an error "The remote server returned an unexpected response: (407) Proxy Authentication Required" chances are it's because you are using a proxy server to access the web. In this case you'll need to add a few extra lines of code at the start of the previous code block to setup the credentials of the DefaultWebProxy.

    //if you're accessing the service via a proxy

    //you may need to specify your credentials

    IWebProxy wproxy = WebRequest.DefaultWebProxy;

 

    wproxy.Credentials = CredentialCache.DefaultNetworkCredentials;

    WebRequest.DefaultWebProxy = wproxy;

Posted: Apr 13 2011, 05:16 by CameronM | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: ASP.NET

Creating a Simple Collection Class

Creating a group of objects that share common properties if one of the key features of Object Orientated programming. An object may represent real-life 'things' such as a person or vehicle, or business related objects such as a documents or reports. One of the simplest ways to create and retrieve such as group of objects is to create a Class in .NET.

Creating a Class

Our sample class represents Avatar images that can be associated with users of our website. We will use the image name as the name of the Avatar and all the images are located in the  same folder on the web server.[hotellink:brisbane]

Select Add New Item from the Visual Studio IDE and create a new Class called Avatar. Visual Studio will create the shell for our new class, which includes a number of default Namespaces as well as the constructor for Avatar.

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
 
/// <summary>
/// Summary description for Avatar
/// </summary>
public class Avatar
{
    public Avatar()
    {
        //
        // TODO: Add constructor logic here
        //
    }
}

As you already know methods in .NET can be overloaded. This means that we can create any number of public Avatar() methods depending on how we want the class to be called. In our example we will allow two ways to create a new Avatar, the first where the name will be set after the object is created and a second where the name is included in the initial call.

Add a private variable to the class that will hold the avatar name a new Property to enable the calling function to get and set the value of this variable. We could set the local variable _name to public so that we could access its value directly, however it is often better to wrap these values as Properties, so that we can add an validation or custom handling that may be required.

public class Avatar
{
    private string _name;
 
    ....
 
    public string Name
    {
        get { return _name;}
        set { _name = value; }
    }
}

We can know create a second constructor for Avatar with a parameter that sets the value of Name.

    public Avatar(string AvatarName)
    {
        this.Name = AvatarName;
    }

Create a Collection

A single Avatar object is not particularly useful, so we will build another class that enables us to quickly and easily add and remove Avatars to a list, or Collection. [silverlightslideshow:example]

Create a new Class called AvatarCollection. As we want this class to act as a collection of objects we need to ensure it inherits from System.Collections.CollectionBase.

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
 
/// <summary>
/// Summary description for AvatarCollection
/// </summary>
public class AvatarCollection : System.Collections.CollectionBase
{
    public AvatarCollection()
    {
        //
        // TODO: Add constructor logic here
        //
    }
}

A simple collection needs to have functionality to add new items. remove a particular item and to return or retrieve a particular item. To enable this we add some very simple methods called Add, Remove and Item.

    public void Add(Avatar av)
    {
        List.Add(av);
    }
 
    public void Remove(int index)
    {
        List.RemoveAt(index);
    }
 
    public Avatar Item(int index)
    {
        return (Avatar)List[index];
    }

The Add method take an Avatar object as a parameter and adds it to the List (or Collection) or objects. As expected, the Remove method removes whatever object is located at the specified index position. Likewise the Item method returns an Avatar object located at the specified index position, notice that we have to explicitly cast the object to an Avatar as List can contain any object type. 

In our example, we would like to create a method that pre-populates the List with all Avatars located within a specific folder on the web server. We can again overload the constructor AvatarCollection to call whatever methods we require.

    public AvatarCollection(string FolderName)
    {
        GetAvatars(FolderName);
    }
 
    public void GetAvatars(string FolderName)
    {
        //retrieve an array of files from the directory
        DirectoryInfo dir = new DirectoryInfo(System.Web.HttpContext.Current.Server.MapPath(FolderName));
        FileInfo[] files = dir.GetFiles();
 
        //create a new Avatar for each file and add to list
        foreach (FileInfo file in files)
        {
            Avatar av = new Avatar(file.Name);
            this.List.Add(av);
        }
    }

The AvatarCollection constructor calls the GetAvatars method which creates an Avatar object for each file in the specified folder and then adds it to the list. By making the GetAvatars method public, it can be called later, if the blank constructor is used. You may need to add some logic to delete any objects already in the list should the user call GetAvatars more than once.

Using the Collection

You can now make use the Avatar object and related collection within your code as a quick and easy DataSource. For instance, the code below sets the datasource of a drop-down list to an AvatarCollection. 

            AvatarCollection av = new AvatarCollection("avatars");
 
            this.AvatarList.DataSource = av;
            this.AvatarList.DataTextField = "Name";
            this.AvatarList.DataBind();

Posted: Mar 25 2010, 17:43 by Admin | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: ASP.NET | C#

Reading XML files with child elements

In the previous post we looked at how to create a DataSet by reading from a simple XML file. In this port we will investigate how .NET handles more complex XML files and in particular how the .NET DataSet handles XML files containing multiple child elements under the root.

<?xml version="1.0" encoding="utf-8" ?>
<AppSettings>
  <setting name="CurrentInstance" serializeAs="String">
    <value>1</value>
    <currentStatus>
      <status>live</status>
      <lastUpdated>01-01-2010</lastUpdated>
    </currentStatus>
  </setting>
  <setting name="OutputDirectory" serializeAs="String">
    <value>\\SV-OCRMGR\mbrc\ocr\xmloutput</value>
    <currentStatus>
      <status>live</status>
      <lastUpdated>01-01-2010</lastUpdated>
    </currentStatus>
  </setting>
</AppSettings>

As we found in the previous post, when .NET parses the XML into the DataSet it creates a DataTable for the root element, in thise case the table is called AppSettings. With the more complex XML shown above, simple elements, like value are parsed into a column of the AppSettings table. Elements that contain child elements themselves, such as currentStatus are parsed into a new DataTable within the DataSet. .NET also creates a relationship, similar to a foreign key relationship you may be familiar with from database development.

We can modify the code from the previous post to take advantage of this functionality.

//declare a new DataSet
DataSet ds = new DataSet();
 
//read the XML file into the DataSet
ds.ReadXml("AppSettings.xml");
 
 
DataRow[] drChildren;
DataRelation dr;
 
//access each node in the XML file using a DataRow
//in this example the nodes we want are in the settings table
foreach (DataRow drResult in ds.Tables["setting"].Rows)
{
    //access the elements of the XML file using the DataRow columns
    //we will just write them to Trace for now
    System.Diagnostics.Trace.Write(drResult["name"].ToString() + " " + drResult["value"].ToString());
 
    //declare the relationship
    dr = ds.Relations[0];
 
    //although we only expect one row of data GetChildRows returns an array
    drChildren = drResult.GetChildRows(dr);
 
    //iterate thru the array of DataRows to access the values
    for (int i = 0; i < drChildren.Length; i++)
    {
        System.Diagnostics.Trace.Write(" " + drChildren[i]["status"].ToString());
    }
    System.Diagnostics.Trace.WriteLine("");
}

 The output from this file (show below) shows that we have returned the status element for each row in the setting table:

CurrentInstance 1 live
OutputDirectory \\SV-OCRMGR\mbrc\ocr\xmloutput live

What isn't clear is how all this works. To illustrate this better, we can write some code to reveal the relationship .NET created between our original setting table and the child element currentStatus.

//declare a new DataSet
DataSet ds = new DataSet();
 
//read the XML file into the DataSet
ds.ReadXml("AppSettings.xml");
 
//iterate through the relationships
foreach (DataRelation dr in ds.Relations)
{
    System.Diagnostics.Trace.WriteLine(dr.RelationName + " " + dr.ParentTable + " " + dr.ChildTable);
 
    foreach (DataColumn dc in dr.ParentColumns)
    {
        System.Diagnostics.Trace.WriteLine(dc.ColumnName);
    }
}

The output of this codes is:

setting_currentStatus setting currentStatus
setting_Id

.NET has created a DataRelation called setting_currentStatus which links the setting table to the currentStatus table in a field called setting_Id. You'll notice the XML file does not have a field called setting_Id, .NET created that when it parsed the file into the DataSet. In our earlier code we took advantage of this relationship by calling the GetChildRows method on each DataRow in setting. GetChildRows takes as its parameter a DataRelation object, which tells .NET everything it needs to know to grab the related child rows.

As we only had one complex child element in our XML, we were able to use the define the correct DataRelation by simply pointing to the first DataRelation in the collection using the code dr = ds.Relations[0]. Obvisously, when our XML has more than one complex child element, we need a way to determine the DataRelation we want to use. Lets modofy the XML file again and add a new element called currentScope.

<?xml version="1.0" encoding="utf-8" ?>
<AppSettings>
  <setting name="CurrentInstance" serializeAs="String">
    <value>1</value>
    <currentStatus>
      <status>live</status>
      <lastUpdated>01-01-2010</lastUpdated>
    </currentStatus>
    <currentScope>
      <scope>user</scope>
      <lastUpdated>01-01-2010</lastUpdated>
    </currentScope>
  </setting>
  <setting name="OutputDirectory" serializeAs="String">
    <value>\\SV-OCRMGR\mbrc\ocr\xmloutput</value>
    <currentStatus>
      <status>live</status>
      <lastUpdated>01-01-2010</lastUpdated>
    </currentStatus>
    <currentScope>
      <scope>application</scope>
      <lastUpdated>01-01-2010</lastUpdated>
    </currentScope>
  </setting>
</AppSettings>

We have a couple of options when defining the DataRelation, one is to use the index as we did previously, which will return the related children in the order they appear in the XML. The second is to use the name of the DataRelation, which as we saw earlier is created by combining the names of the parent and child tables. Either way, we need to know the structure of the XML file and be confident that it is not going to change too dramatically. Lets modify the code to use the DataRelation name to retrieve the child rows from the newly added currentScope element.

//declare a new DataSet
DataSet ds = new DataSet();
 
//read the XML file into the DataSet
ds.ReadXml("AppSettings.xml");
 
 
DataRow[] drChildren;
DataRelation dr;
 
//access each node in the XML file using a DataRow
//in this example the nodes we want are in the settings table
foreach (DataRow drResult in ds.Tables["setting"].Rows)
{
    //access the elements of the XML file using the DataRow columns
    //we will just write them to Trace for now
    System.Diagnostics.Trace.Write(drResult["name"].ToString() + " " + drResult["value"].ToString());
 
    //declare the relationship
    dr = ds.Relations["setting_currentScope"];
 
    //although we only expect one row of data GetChildRows returns an array
    drChildren = drResult.GetChildRows(dr);
 
    //iterate thru the array of DataRows to access the values
    for (int i = 0; i < drChildren.Length; i++)
    {
        System.Diagnostics.Trace.Write(" " + drChildren[i]["scope"].ToString());
    }
    System.Diagnostics.Trace.WriteLine("");
}

The output from this code:

CurrentInstance 1 user
OutputDirectory \\SV-OCRMGR\mbrc\ocr\xmloutput application

Posted: Mar 11 2010, 17:41 by CameronM | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: ASP.NET | ASP.NET | ASP.NET | C# | ASP.NET | C# | C# | XML | C# | XML | XML | XML

N-Tier Architecture using Datasets

In our posts on using Datasets, Using Strongly Typed Datasets and Adding Additional Queries to a Dataset we outlined a simple 2-tier architecture. This may be suitable for many applications, however it is common to move larger and more complicated applications to an N-tier architecture. To achieve this we can add Business Logic Layer in between our application (the actual aspx pages) and the Data Access Layer containing our Datasets.

To seperate out layers in the web site, create a new folder called BLL under the App_Code folder. The image below shows the structure of the App_Code folder, with the documents that will be created in this post.

In the BLL folder add a new Class called CustomerData

We now need to add a reference to our DAL Customers dataset and implement a few methods to make the data available for use. The code snippet is shown below.

    public class CustomerData
    {
        public CustomerData()
        {
        }
 
        public Customers.CustomersDataTable GetAllCustomers()
        {
            CustomersTableAdapter adp = new CustomersTableAdapter();
            return adp.GetData();
        }
 
        public Customers.CustomersRow GetCustomerByCustomerID(string ID)
        {
            CustomersTableAdapter adp = new CustomersTableAdapter();
            return GetFirstRow(adp.GetCustomersByID(ID));
        }
 
        private Customers.CustomersRow GetFirstRow(Customers.CustomersDataTable table)
        {
            Customers.CustomersRow row;
            row = table.Rows[0] as Customers.CustomersRow;
            return row;
        }
    }

Basically we want to create methods in our BLL class that provide access to each method in the DAL dataset. So in our case we create firstly a method that returns all customers, calling the GetData() method. Secondly, we create a method that returns a single row based on the CustomerID and using the GetCustomersByID method of the Customers dataset. A helper method called GetFirstRow is used to grab just the first row from the DataTable that is returned my the GetCustomersByID method.

Once the CustomerData class has been built, it is a relatively simple task to bind the GridView on out CustomerList.aspx page to the class. Choose Configure Data Source from the ObjectDataSource and select Sample.BusinessLogicLayer.CustomerData from the dropdown list, and click next. In the Choose a method dropdown list, select the appropriate method, in this case GetCustomerByCustomerID.

The Parameters remain unchanged so you can click Next and then Finish. Run the page to see the results.

Posted: Nov 06 2009, 23:03 by Admin | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: ASP.NET | C#

Adding Additional Queries to a Dataset

In our first post on 2-tier architecure Using Strongly Typed Datasets, we created a very simple dataset based on the Customers table in the Northwind database. We are now going to expand upon this simple dataset and add the abilty to return records based on parameters, such as CustomerID.

Opne the Customers.xsd Dataset we created in the previous post and right mouse click on the CustomersTableAdapter heading to open the popup menu. Select Add Query to launsh the TableAdapter Query Configuration Wizard.

  1. Choose Use SQL statements
  2. Choose the SELECT with returns rows option
  3. Type the following SQL statement and click next

SELECT CustomerID, CompanyName, Address, City, PostalCode
FROM Customers
WHERE CustomerID=@ID

Unselect the Fill a DataTable option and rename the Method GetCustomersByID, click next and finish.

 

Build the web site to cofirm it compiles and then open the CustomerList.aspx file we created in the first post. To utilise our new query that expects a CustomerID, we need to add some extra fields to the page. Add a textbox called txtCustomerID and a button called btnSearch.

Next we need to bind the GridView to the new datatable, so select Configure Data Source from the ObjectDataSource Tasks popup. click through until you get the the Define Data Methods page of the wizard. In the Choose a Method dropdown list you will see that we now have two methods available. Select the GetCustmersByID() method.

 

Next we need to define where the data for the parameter @ID will come from. In the Define Parameters screen there are a number of source, including QueryString and Session objects, as well as an option to select a control. We will be getting our information from the textbox called txtCustomerID, so go ahead and define the parameter as shown below. Although it's not manditory, it will be easier to assign a default customerID so that when the page loads the GridView will display one record. If we did not want to select a default value, we would have to handle binding via code, so that we did not attempt to bind the GridView to an empty datatable.

Run the page and check the results. You should see the GridView populated with the record for customer Alfreds Futterkiste.

 

If you enter a different CustomerID, for instance BOTTM and click the button, the page will pstback and display the record for Bottom-Dollar Markets.

Obviously this is a very limited search option, as we need to know the exact customerID to search for. With a little more tweaking, it would be easy to add wildcards to our query or to even add the ability to search on more than one field, so have fun.

Posted: Nov 06 2009, 22:31 by Admin | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: C# | ASP.NET | C#

Using Strongly Typed Datasets

Creating and using a strongly-typed Dataset in ASP.NET provides an effective 2-tier architecture. Using the Northwind SQL Server database, in this post we will create a simple Dataset for use with some data-bound controls on an ASP.NET webpage.

To get started, add a folder called DAL, short for Data Access Layer, under the App_Code folder in a standard ASP.NET Web Site. In this folder, create a new Dataset called Customers.

Visual Studio will create the Dataset and launch the TableAdapter Configuration Wizard to guide you through the process of setting up the Dataset.

  1. Select an existing Connection, or if you haven't got a connection to Northwind already saed, hit the New Connection button.
  2. Choose the Use SQL statements option
  3. Enter the following SQL statement, or click the Query Builder button to visually create a simple SELECT query.
SELECT CustomerID, CompanyName, Address, City, PostalCode
FROM Customers

Visual Studio creates the Dataset complete with a TableAdapter. Build your web site, to make sure it compiles.

To show how easy it is to use this Dataset, create a new blank page in your ASP.NET web site called CustomerList and drag in a GridView control from the Toolbox. From the GridView Tasks popup, select <New Data Source> from the Choose Data Source drop-down list. The Data Source Configuration Wizard will open prompting you to select the source of your data. Normally you probably selected Database to connect to a SQL Server database, but to use our new Customers Dataset we need to select Object.

From the list of objects, select the CustomerTableAdapter.

Next, the wizard will display all the available methods that return DataTables. In our case there is only one, called GetData.

That's all there is to do. Our GridView is now bound to the DataSet. Fire up the webpage and see the results.

Posted: Nov 06 2009, 21:30 by Admin | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: ASP.NET | C#