http://www.imomin.webs.com

Thank You for Visit Me

Md. Mominul Islam

view:  full / summary

Posting Form Data from ASP.NET Page to Another URL Using Post Method

Posted by imomins on September 26, 2012 at 8:05 AM Comments comments (0)

Introduction

 

Sometime you need to post a form to an different url from asp.net pages, for example you might need to send user to third party payment processing system using post method, asp.net does not provide any straight forward way to accomplish this task.

Problem which most users faces with server side form in aspx page are, you are not allowed to change action of form and you are allowed to use only one server side form per page.

Possible Solutions

  1. One possible solution to this problem is to Create your own form control and use it on page this will allow you to change action of form, but again what if you do not want some existing input elements in current page to go to post.
  2. There is good way to post form data using HttpWebResponse & HttpWebRequest class if you want to post data behind the scenes, but if you want to post data using user browser then you are stuck.

Our Solution

I will try to show you one possible way to accomplish this task, we will create

  1. component that will create form with required fields and post the form to specified url, 
  2. web page that will use that component to post data and 
  3. page which will receive that data and display posted data.

A) RemotePost Class.

public class RemotePost
{
private System.Collections.Specialized.NameValueCollection Inputs = new System.Collections.Specialized.NameValueCollection();
public string Url = "";
public string Method = "post";
public string FormName = "form1";
public void Add(string name,string value)
{
Inputs.Add(name,
value);
}
public void Post()
{
System.Web.HttpContext.Current.Response.Clear();
System.Web.HttpContext.Current.Response.Write("");
System.Web.HttpContext.Current.Response.Write(
string.Format("",FormName));
System.Web.HttpContext.Current.Response.Write(
string.Format("",FormName,Method,Url))
for(int i=0;i< Inputs.Keys.Count;i++)
{
System.Web.HttpContext.Current.Response.Write(
string.Format("",Inputs.Keys[i],Inputs[Inputs.Keys[i]]));
}
System.Web.HttpContext.Current.Response.Write("");
System.Web.HttpContext.Current.Response.Write("");
System.Web.HttpContext.Current.Response.End();
}
}

 

Properties of our component 

  1. "Url" which is action of our form. 
  2. "Method" which is Method of our form, default is Post but you can also use Get 
  3. "FormName" which is name of form.

Methods of our component. 

  1. "Add" which will be used to add form input name and value. and 
  2. "Post" which will render html on page to do actual posting, most important part of this method is onload event of rendered html's body which will post form to specified URL.

and private field Inputs which will hold name value pair collection of all inputs that goes into form.

you can compile this class to dll and use in your project but for simplicity I am including that class directly into page itself.

B) Sample Page.

Following is sample page code which posts form to specified url.

RemotePost myremotepost = new RemotePost();
myremotepost.Url = http://www.jigar.net/demo/HttpRequestDemoServer.aspx;
myremotepost.Add("field1","Huckleberry");
myremotepost.Add("field2","Finn");
myremotepost.Post() ;

 

C) Receiving Page.

Following is sample page code which posts form to specified url.

This is the page where posting will occur for simplicity we will just write posed value so that we can know what was posted.

<%@ Page Language="C#" %>
<script runat="server">
void Page_Load(object sender, EventArgs e){
if (Request.Form["field1" != null ){
Response.Write("field1 : " + Request.Form["field1" + "")}
if(Request.Form["field2" != null ){
Response.Write("field2 : " +Request.Form["field2" + "")}
}
</script> 

 

Run Sample

Click "http://www.jigar.net/demo/RemotePost.aspx" target="new">here to run sample

There will be cases where you will need to tweak the code to suit your requirement. you will also need to check scenario where user uses back button of browser(from posted page) which will cause form to be posted again.

Integrate Google Map With ASP.NET

Posted by imomins on September 23, 2012 at 6:55 AM Comments comments (0)

<%@ Page Title="" Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" CodeFile="Geocoding.aspx.cs" Inherits="ReverseGeocoding" %>

 

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">

<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false" mce_src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>

<script language="javascript" type="text/javascript">

 

    var map;

    var geocoder;

    function InitializeMap() {

 

        var latlng = new google.maps.LatLng(-34.397, 150.644);

        var myOptions =

        {

            zoom: 8,

            center: latlng,

            mapTypeId: google.maps.MapTypeId.ROADMAP,

            disableDefaultUI: true

        };

        map = new google.maps.Map(document.getElementById("map"), myOptions);

    }

 

    function FindLocaiton() {

        geocoder = new google.maps.Geocoder();

        InitializeMap();

 

        var address = document.getElementById("addressinput").value;

        geocoder.geocode({ 'address': address }, function (results, status) {

            if (status == google.maps.GeocoderStatus.OK) {

                map.setCenter(results[0].geometry.location);

                var marker = new google.maps.Marker({

                    map: map,

                                   });

 

            }

            else {

                alert("Geocode was not successful for the following reason: " + status);

            }

        });

 

    }

 

 

    function Button1_onclick() {

        FindLocaiton();

    }

 

    window.onload = InitializeMap;

 

</script>

 

<h2>Gecoding Demo JavaScript: </h2>

<table>

<tr>

<td>

    <input id="addressinput" type="text" style="width: 447px" mce_style="width: 447px" />   

</td>

<td>

    <input id="Button1" type="button" value="Find" onclick="return Button1_onclick()" /></td>

</tr>

<tr>

<td colspan ="2">

<div id ="map" style="height: 253px" mce_style="height: 253px" >

</div>

</td>

</tr>

</table>

</asp:Content>

 

 

Integrate Google Map With ASP.NET

Posted by imomins on September 23, 2012 at 6:35 AM Comments comments (0)

Google Maps API V3 for ASP.NET


 
 

Introduction

Google Maps provides a flexible way to integrate maps to provide directions, location information, and any other kind of stuff provided by the Google Maps API in your web application. Although there are some articles in CP explaining about maps, in my article I am going to provide information about the latest Google Maps API V3 version. In this article, we will see some of the common techniques that are used with Google Maps. In order to work with the code sample explained below, you need to have some basic knowledge about JavaScript and C#.

Your First Google Maps Map

In the earlier versions of the Google Maps API, as a developer we need to register the web application with Google and we were supposed to get an API key. However with the release of the new version, key registration has been eliminated for a few days for now, but recently, Google has come up with some kind of traffic limitations and we are supposed to register the application with an API Key. You can get more information about the usage of the API and the terms at this link: http://code.google.com/apis/maps/documentation/javascript/usage.html#usage_limits. Now we will start our work and create a simple Google Maps map that can be integrated into our site. The following script is used to connect to the Google Maps API:

<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false">
</script>

In order to create a simple Google Map map, you can use the following JavaScript code:

function InitializeMap() 
{
    var latlng = new google.maps.LatLng(-34.397, 150.644);
    var myOptions = {
        zoom: 8,
        center: latlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    var map = new google.maps.Map(document.getElementById("map"), myOptions);
}
window.onload = InitializeMap;

FirstGoogleMap

Google Maps Options

In the above example, we used the Map class which takes options and an HTML ID as parameters. Now moving further, we will look at the map options:

function initialize() {
    var latlng = new google.maps.LatLng(-34.397, 150.644);
    var options =
    {
        zoom: 3,
        center: new google.maps.LatLng(37.09, -95.71),
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        mapTypeControl: true,
        mapTypeControlOptions:
        {
            style: google.maps.MapTypeControlStyle.DROPDOWN_MENU,
            poistion: google.maps.ControlPosition.TOP_RIGHT,
            mapTypeIds: [google.maps.MapTypeId.ROADMAP, 
              google.maps.MapTypeId.TERRAIN, 
              google.maps.MapTypeId.HYBRID, 
              google.maps.MapTypeId.SATELLITE]
        },
        navigationControl: true,
        navigationControlOptions:
        {
            style: google.maps.NavigationControlStyle.ZOOM_PAN
        },
        scaleControl: true,
        disableDoubleClickZoom: true,
        draggable: false,
        streetViewControl: true,
        draggableCursor: 'move'
    };
    var map = new google.maps.Map(document.getElementById("map"), options);
}
window.onload = initialize;

In the above example, all the properties of Map have been used. You can set the map options depending on your requirements.

MapOptions

The properties of the Map class are summarized in the following table:

Property Class
MapTypeControl:true/false mapTypeControlOptions
Property Constants/Values
style
DEFAULT<br />
HORIZONTAL_BAR<br />
DROPDOWN_MENU
position
BOTTOM<br />
BOTTOM_LEFT<br />
BOTTOM_RIGHT <br />
LEFT<br />
RIGHT<br />
TOP<br />
TOP_LEFT<br />
TOP_RIGHT
mapTypeIds
ROADMAP<br />
SATELLITE<br />
Hybrid<br />
Terrain
navigationControl:true/false navigationControlOptions
Property Constants/Values
Position
BOTTOM<br />
BOTTOM_LEFT<br />
BOTTOM_RIGHT<br />
LEFT<br />
RIGHT<br />
TOP<br />
TOP_LEFT<br />
TOP_RIGHT T
style
DEFAULT<br />
SMALL<br />
ANDROID
scaleControl:true/false scaleControlOptions: scalecontroloptions has the same properties as navigation control options (position, style) and behavior is also the same.
disableDoubleClickZoom: true/false
scrollwheel: true/false
draggable: true/false
streetViewControl: true/false

Map Marker

The Marker class provides you with an option to display a marker to the user for a given location. Use of the marker is a very general task that we will use often in our application. The following example shows you how to create a simple marker.

var marker = new google.maps.Marker
(
    {
        'Click me'
    }
);

Marker

Info Window

With the marker displayed on the map, you create an onclick event which provides the user with a popup window showing the information about the place. You can create an info window as shown below:

var infowindow = new google.maps.InfoWindow({
    content: 'Location info:
    Country Name:
    LatLng:'
});
google.maps.event.addListener(marker, 'click', function () {
    // Calling the open method of the infoWindow 
    infowindow.open(map, marker);
});

Combining them:

var map;
function initialize() {
    var latlng = new google.maps.LatLng(-34.397, 150.644);
    var myOptions = {
        zoom: 8,
        center: latlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    map = new google.maps.Map(document.getElementById("map"), myOptions);
    var marker = new google.maps.Marker
    (
        {
            'Click me'
        }
    );
    var infowindow = new google.maps.InfoWindow({
        content: 'Location info:<br/>Country Name:<br/>LatLng:'
    });
    google.maps.event.addListener(marker, 'click', function () {
        // Calling the open method of the infoWindow 
        infowindow.open(map, marker);
    });
}
window.onload = initialize;

With this complete, you are going to create a map and then locate the region of the user, load the map with a marker and the info window.

InfoWindow

Multiple Markers

In some cases, if you want to handle multiple markers, you achieve this like the following:

function markicons() {
   InitializeMap();

        var ltlng = [];

        ltlng.push(new google.maps.LatLng(17.22, 78.28));
        ltlng.push(new google.maps.LatLng(13.5, 79.2));
        ltlng.push(new google.maps.LatLng(15.24, 77.16));

        map.setCenter(ltlng[0]);
        for (var i = 0; i <= ltlng.length; i++) {
            marker = new google.maps.Marker({
                map: map,
                (function (i, marker) {

                google.maps.event.addListener(marker, 'click', function () {

                    if (!infowindow) {
                        infowindow = new google.maps.InfoWindow();
                    }

                    infowindow.setContent("Message" + i);

                    infowindow.open(map, marker);

                });

            })(i, marker);

        }
}

mulitplemarkers

Directions

One of the most useful features of the Google Maps API is it can be used to provide directions for any given location(s). The following code is used to accomplish this task:

var directionsDisplay;
var directionsService = new google.maps.DirectionsService();

function InitializeMap() {
    directionsDisplay = new google.maps.DirectionsRenderer();
    var latlng = new google.maps.LatLng(-34.397, 150.644);
    var myOptions =
    {
        zoom: 8,
        center: latlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
    var map = new google.maps.Map(document.getElementById("map"), myOptions);

    directionsDisplay.setMap(map);
    directionsDisplay.setPanel(document.getElementById('directionpanel'));

    var control = document.getElementById('control');
    control.style.display = 'block';


}
    function calcRoute() {

    var start = document.getElementById('startvalue').value;
    var end = document.getElementById('endvalue').value;
    var request = {
        origin: start,
        destination: end,
        travelMode: google.maps.DirectionsTravelMode.DRIVING
    };
    directionsService.route(request, function (response, status) {
        if (status == google.maps.DirectionsStatus.OK) {
            directionsDisplay.setDirections(response);
        }
    });

}

function Button1_onclick() {
    calcRoute();
}

window.onload = InitializeMap;

Directions

Layers

The Google Maps API provides you with multiple layer options of which one is bicycle. By using the bicycle layer, you can show bicycle paths for a particular location on the map to users. The following code snippet allows you to add a bicycle layer to a map.

var map 
function InitializeMap() {
    var latlng = new google.maps.LatLng(-34.397, 150.644);
    var myOptions = {
        zoom: 8,
        center: latlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
   map = new google.maps.Map(document.getElementById("map"), myOptions);
}
window.onload = InitializeMap;
var bikeLayer = new google.maps.BicyclingLayer();
bikeLayer.setMap(map);

Gecoding

So far we have learned the basic concepts of creating Google maps and displaying information about a location to the user. Now we will see how we can calculate/find a location specified by the user. Geocoding is nothing but the process of finding out the latitude and longitude for a given region. The following API code shows you how to find the latitude and longitude for a location.

geocoder.geocode({ 'address': address }, function (results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
        map.setCenter(results[0].geometry.location);
        var marker = new google.maps.Marker({
            map: map,
            }
    else {
        alert("Geocode was not successful for the following reason: " + status);
    }
});

Geocoding C#

The same calculation can also be performed by using C#:

public static Coordinate GetCoordinates(string region)
{
    using (var client = new WebClient())
    {

        string uri = "http://maps.google.com/maps/geo?q='" + region + 
          "'&output=csv&key=ABQIAAAAzr2EBOXUKnm_jVnk0OJI7xSosDVG8KKPE1" + 
          "-m51RBrvYughuyMxQ-i1QfUnH94QxWIa6N4U6MouMmBA";

        string[] geocodeInfo = client.DownloadString(uri).Split(',');

        return new Coordinate(Convert.ToDouble(geocodeInfo[2]), 
                   Convert.ToDouble(geocodeInfo[3]));
    }
}

public struct Coordinate
{
    private double lat;
    private double lng;

    public Coordinate(double latitude, double longitude)
    {
        lat = latitude;
        lng = longitude;

    }

    public double Latitude { get { return lat; } set { lat = value; } }
    public double Longitude { get { return lng; } set { lng = value; } }

}

Reverse Geocoding

As the name indicates, it is the reverse process of geocoding; that is depending on the latitude and longitude, we can find the location name. This can be achieved using the following code:

var map;
var geocoder;
function InitializeMap() {

    var latlng = new google.maps.LatLng(-34.397, 150.644);
    var myOptions =
    {
        zoom: 8,
        center: latlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        disableDefaultUI: true
    };
    map = new google.maps.Map(document.getElementById("map"), myOptions);
}

function FindLocaiton() {
    geocoder = new google.maps.Geocoder();
    InitializeMap();

    var address = document.getElementById("addressinput").value;
    geocoder.geocode({ 'address': address }, function (results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
            map.setCenter(results[0].geometry.location);
            var marker = new google.maps.Marker({
                map: map,
                if (results[0].formatted_address) {
                region = results[0].formatted_address + '<br/>';
            }
            var infowindow = new google.maps.InfoWindow({
                content: 'Location info:<br/>Country Name:' + region + 
                '<br/>LatLng:' + results[0].geometry.location + ''
            });
            google.maps.event.addListener(marker, 'click', function () {
                // Calling the open method of the infoWindow 
                infowindow.open(map, marker);
            });

        }
        else {
            alert("Geocode was not successful for the following reason: " + status);
        }
    });
}

Reverse Geocoding in C#

The following C# code shows you the reverse geocoding technique:

static string baseUri = 
  "http://maps.googleapis.com/maps/api/geocode/xml?latlng={0},{1}&sensor=false";
string location = string.Empty;

public static void RetrieveFormatedAddress(string lat, string lng)
{
    string requestUri = string.Format(baseUri, lat, lng);

    using (WebClient wc = new WebClient())
    {
        string result = wc.DownloadString(requestUri);
        var xmlElm = XElement.Parse(result);
        var status = (from elm in xmlElm.Descendants() where 
            elm.Name == "status" select elm).FirstOrDefault();
        if (status.Value.ToLower() == "ok")
        {
            var res = (from elm in xmlElm.Descendants() where 
                elm.Name == "formatted_address" select elm).FirstOrDefault();
            requestUri = res.Value;
        }
    }
}

Conclusion

In this article, I have tried to explain some of the basic and most frequently used tasks of the Google Maps API V3. Hope this article will help you in completing your tasks. Further, there are lot more things in the API which I have not discussed and I would try to include them in my future updates of this article. Any comments and feedback are always welcome.

External Resources

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

S V Saichandra
Software Developer
India India
Member
S V Sai Chandra is a Software Engineer from Hyderabad Deccan. He started Embedded Programing in his college days and now he is a Web Developer by Profession. He Loves coding and his passion is always been towards Microsoft Technologies. Apart from coding his other hobbies include reading books, painting and hang out with friends is his most favorite past time hobby.
He blogs at
http://technowallet.blogspot.com
Technical Skills:
C#,Ado.Net,Asp.Net,Sql Server,JavaScript,XML,Web services.

Rate this:   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Search this forum  

Profile popups    Noise Very HighHighMediumLowVery Low   Layout NormalExpand Posts onlyExpand AllThread ViewNo JavascriptNo JS + Preview   Per page 102550    


GeneralMy vote of 5 PinmemberAbinash Bishoyi18:50 20 Aug '12  
QuestionHow to add image to marker [modified] Pinmemberfootballpardeep15:37 10 Aug '12  
QuestionUsing Json google reverse geocoder Pinmemberdonpp464:55 12 Jul '12  
QuestionGpoogle map registration

get IP

Posted by imomins on September 19, 2012 at 8:05 AM Comments comments (0)

 

System.Net.IPHostEntry IP = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName());

System.Net.IPAddress[] IPAddr = IP.AddressList;

if (IPAddr.Length > 1)

{

strMachineNameIP = Convert.ToString(System.Environment.MachineName) + " ## " + Convert.ToString(System.Environment.UserName) + " ## " + IPAddr[1].ToString();

}

else if (IPAddr.Length > 0)

{

strMachineNameIP = Convert.ToString(System.Environment.MachineName) + " ## " + Convert.ToString(System.Environment.UserName) + " ## " + IPAddr[0].ToString();

}

else

{

strMachineNameIP = Convert.ToString(System.Environment.MachineName) + " ## " + Convert.ToString(System.Environment.UserName);

}


Seria Key Of SQL Server

Posted by imomins on September 19, 2012 at 12:25 AM Comments comments (0)

SQL Server 2008 Enterprise: A comprehensive data platform that meets the high demands of enterprise online transaction processing and data warehousing applications. Unlock SQL Server 2008 Enterprise with the following key: MQWT2-9MKBY-K8PXQ-6K4BW-TY4BD.

 

 

SQL Server 2008 Standard: Complete data management and business intelligence platform, providing best-in-class ease of use and manageability for running departmental applications. Unlock SQL Server 2008 Standard with the following key: XP4FP-3VTDK-37TWH-TW77J-9MFM3.

 

 

SQL Server 2008 Evaluation: Trial version to build and test any type of application. It includes all of the functionality of SQL Server 2008 Enterprise, but is licensed only for development, test, and demo use. (No product key is required to unlock. This is the default version).

 

Download : Microsoft SQL Server 2008 10.00.1442.32 RC0

Block Site in PC

Posted by imomins on September 12, 2012 at 1:45 AM Comments comments (0)

আপনার পরিবারে যদি কোন জুনিয়র টাইপের কেউ থেকে থাকে, আর আপনি যদি এরকম আশংকা করেন যে, ওরা কেউ এডাল্ট ওয়েব ভিজিট করতে পারে; কিংবা আপনি যদি কোন ওয়েবসাইটকে আপনার পিসিতে ব্লক করে রাখতে চান তাহলে  আপনার কাজে লাগবে।

 

প্রথমে মাই কম্পিউটার থেকে সি ড্রাইভে প্রবেশ করুন। ড্রাইভ C:\ থেকে windows এ যান । তারপর System32 তে প্রবেশ করুন। এখন Drivers এ গিয়ে etc ফোল্ডারে যান।
এখানে Hosts নামে একটা ফাইল দেখতে পাবেন। নোটপ্যাড দিয়ে এটা খুলুন। একেবারে নিচের দিকে দেখতে পাবেন এই 127.0.0.1 Localhost
লেখাটি। ঠিক এর নিচে লিখুন 127.0.0.2 এবং আপনার ওয়েবসাইটের ঠিকানা ।

যেমন: 127.0.0.2 http://www.mininova.com
127.0.0.3 http://www.blockinternet.com
127.0.0.4 http://www.facebook.com

এভাবে আপনি যত ইচ্ছা তত সাইট যোগ করতে পারবেন। তবে মনে রাখবেন 127.0.0.1 Localhost কিন্তু কখনোই পরিবর্তন করবেন না। নতুন ওয়েবসাইট শুধু এর নিচে : 127.0.0.2
127.0.0.3
127.0.0.4 এভাবে পর্যায়ক্রমে যোগ করবেন। তারপর নোটপ্যাডটি সেভ করে বেরিয়ে আসুন।

How to pass the Odesk ASP.Net 3.5 using C# Test 2012

Posted by imomins on September 8, 2012 at 6:30 AM Comments comments (1)

How to pass the Odesk ASP.Net 3.5 using C# Test 2012


Hello to every one. in this tutorial i will show you how to pass the odesk ASP.Net 3.5 using C# Test 2012.
 Question1:
The earliest event in which all viewstate information has been restored is:


    a.    Init
    b.    PreLoad
    c.    Load
    d.    Render

 the answer is:
    b.    PreLoad       

 Question2:
Which of the following differentiates a UserControl from a Custom Server control?


    a.    UserControl can directly express rendering information via markup; a Custom Server control can not.
    b.    UserControl does not require the use of the @Register directive; a Custom Server control does require it.
    c.    UserControl can make use of script based validation;  a Custom Server control can not.
    d.    UserControl can represent complete compositate hierarchy; a Custom Server control can not.

 the answer is:
    b.    UserControl does not require the use of the @Register directive; a Custom Server control does require it.       

 Question3:
What is the proper declaration of a method which will handle the following event?

Class MyClass
{
      public event EventHandler MyEvent;
}


    a.    public void A_MyEvent(object sender, MyArgs e)
{
}
    b.    public void A_MyEvent(object sender, EventArgs e)
{
}
    c.    public void A_MyEvent(MyArgs e)
{
}

 the answer is:
c.    public void A_MyEvent(MyArgs e)
{
}
       

 Question4:
Given the code below, which items will cause a compilation error?

static void F1(params int [] y)
{
}

static void Sample()
{
   int [] j = new Int32[3];
List k = new List();
// ANSWER GOES HERE
}


    a.    F1(j);
    b.    F1(k);
    c.    F1(1, 2, 3);
    d.    F1(new [] {1,2,3})
    e.    None of the above

 the answer is:
    e.    None of the above       

 Question5:
By which of the following can the .NET class methods be included in .aspx files?


    a.    Including .Net code within the script element with the runat attribute set to server
    b.    Including .Net code within the code element
    c.    Including .Net code using the @code directive on the page
    d.    Including .Net code within the execute attribute of the individual control

 the answer is:
    c.    Including .Net code using the @code directive on the page
       
 Question6:
Which of the following are true about System.Security.Cryptography under version 3.5 of the framework?


    a.    Support is provided for the "Suite B" set of cryptographic algorithms as specified by the National Security Agency (NSA).
    b.    Cryptography Next Generation (CNG) classes are supported on XP and Vista systems.
    c.    The System.Security.Cryptography.AesManaged class allows custom block size, iteration counts and feedback modes to support any Rijndael based encryption.

 the answer is:
    b.    Cryptography Next Generation (CNG) classes are supported on XP and Vista systems.       

 Question7:
Where should an instance of an object which provides services to all users be stored?


    a.    ApplicationState
    b.    SessionState
    c.    ViewState
    d.    None of the above

 the answer is:
    d.    None of the above       

 Question8:
Which of the following are the goals of the Windows Communciation Foundation?


    a.    Bringing various existing communication technologies into a unified environment.
    b.    Cross vendor/platform communication.
    c.    Support for asynchronous communications.
    d.    Support for distributed applications based on technologies such as MSMQ and/or COM+
    e.    All of the above

 the answer is:
    e.    All of the above       

 Question9:
When using a DataReader to access the results of a Database operation, which of the following is true?


    a.    The DataReader provides a cursor that can be used to move forward and backwards through the result.
    b.    The DataReader provides random access capabilities on the result.
    c.    The DataReader can provide the Schema information of the result to the application code.

 the answer is:
    b.    The DataReader provides random access capabilities on the result.       

 Question10:
Which of the following types guarantee atomic reads and writes?


    a.    int
    b.    double
    c.    long
    d.    float

 the answer is:
    d.    float       

 Question11:
Which of the following does Event Bubbling allow composite controls to perform?


    a.    Propagate container related events to the child controls.
    b.    Propagate child events up to control hierarchy
    c.    Distribute events between peer child controls.
    d.    Translate control unhandled control events into exceptions.

 the answer is:
    b.    Propagate child events up to control hierarchy       

 Question12:
Which of the following is/are true regarding the use of Authentication to control access to the HTML file (.htm or .html)?


    a.    ASP.NET authentication handles these by default in a manner equivalent to .aspx pages
    b.    ASP.NET authentication can be associated with these extensions using aspnet_isapi.dll in IIS 6.0, for the appropriate directory
    c.    ASP.NET authentication cannot be used for this purpose

 the answer is:
    c.    ASP.NET authentication cannot be used for this purpose       

 Question13:
Which of the following is false about declarative attributes?


    a.    They must be inherited from the System.Attribute.
    b.    Attribute classes may be restricted to be applied only to application element types.
    c.    By default, a given attribute may be applied multiple times to the same application element.

 the answer is:
    c.    By default, a given attribute may be applied multiple times to the same application element.       

 Question14:
Which of the following is false about System.GC under version 3.5 of the .NET Framework?


    a.    You can request that the garbage collector processes a generation if it determines that it is appropriate at specific points in your code
    b.    You can control the intrusiveness of the garbage collector (how often it performs collections) while your program is running
    c.    You can control the intrusiveness of the garbage collector (how often it performs collections) only during application initialization

 the answer is:
    b.    You can control the intrusiveness of the garbage collector (how often it performs collections) while your program is running       

 Question15:
With which of the following are Declarative Databinding expressions delimited?


    a.    <%#    %>
    b.    <%--   --%>
    c.  
    d.    <#  >

 the answer is:
<%--   --%>       

 Question16:
Which of the following statements are applicable in LINQ to SQL?


    a.    It is pure Object Relational (O/R) model.
    b.    It is a set of enhancements to the DataSet and DataTable classes.
    c.    It requires the use of SQLServer as the database.
    d.    Because LINQ is based on Queries, it can not be used to modify the data in the database.

 the answer is:
    b.    It is a set of enhancements to the DataSet and DataTable classes.       

 Question17:
Which of the following is used to remove a cookie from a client machine?


    a.    Remove the cookie from the System.Web.UI.Page.Request.Cookies collection.
    b.    Remove the cookie from the System.Web.UI.Page.Request.Browser.Cookies collection.
    c.    Set the Expires property to DataTime.Now for a cookie in the Web.UI.Page.Response.Cookies
    d.    Remove the cookie from the System.Web.UI.Page.Response.Cookies collection.

 the answer is:
    d.    Remove the cookie from the System.Web.UI.Page.Response.Cookies collection.       

 Question18:
Which of the following are true of using ADO.NET DataSets and DataTables?


    a.    The DataSets and DataTables objects requires continuous connection to the database
    b.    All tables in a dataset must come from the same database
    c.    A given instance of a DataTable can be in only one DataSet
    d.    Content from multiple DataSets can easily be combined into a single DataSet that contains the net result of all changes

 the answer is:
    b.    All tables in a dataset must come from the same database       

 Question19:
The following are two statements related to System.DateTimeOffset namespace.

Statement X: DateTimeOffset values can be converted to DateTime values and vice versa.
Statement Y: DateTimeOffset does not supports arithmetical operations


    a.    Statement X is incorrect and Statement Y is correct
    b.    Statement X is correct and Statement Y is incorrect
    c.    Both Statements X, Y are correct
    d.    Both Statements X, Y are incorrect

 the answer is:
    d.    Both Statements X, Y are incorrect       

 Question20:
Which of the following are true regarding System.Web.Mail and System.Net.Mail namespaces?


    a.    System.Web.Mail is not supported under version 3.5 of the Framework
    b.    System.Web.Mail is deprecated under version 3.5 of the Framework, and it is officially recommended that System.Net.Mail be used.
    c.    System.Web.Mail is the preferred solution when using IIS hosted applications
    d.    There are no functional differences; the items were moved to a new namespace to better reflect their applicability

 the answer is:
    b.    System.Web.Mail is deprecated under version 3.5 of the Framework, and it is officially recommended that System.Net.Mail be used.       

 Question21:
In which file are Predefined Client Side Validation Scripts defined?


    a.    WebUIValidation.js
    b.    ClientValidation.js
    c.    AspNetValidation.js
    d.    USerValidation.js

 the answer is:
    d.    USerValidation.js       

 Question22:
Which of the following are common methods of supplying "Help" information to an ASP.NET application?


    a.    Setting the ToolTip property of a control to a string containing the information.
    b.    using the open method of the browser window object to open a new browser window and display a help related ASP.NET page
    c.    Using the showHelp method of the browser window object to display a topic from a compiled help file (.chm).
    d.    All of the above

 the answer is:
    c.    Using the showHelp method of the browser window object to display a topic from a compiled help file (.chm).       

 Question23:
When using Cascading Style Sheets (CSS) to format output, which of the following is/are true?


    a.    Styles can be applied to all elements having the same CSS Class attribute
    b.    Styles can be applied to specific elements based on their ID attribute
    c.    Styles can be applied to elements based on their position in a hierarchy
    d.    Styles can be used to invoke script based code
    e.    All of the above

 the answer is:
    e.    All of the above       

 Question24:
Which of the following is false regarding System.Threading.ReaderWriterLockSlim?


    a.    It is optimized for single processor/core operations
    b.    A thread which has a read lock on a resource may not acquire a write lock on the same resource
    c.    By default, a thread which has a read lock on a resource and attempts to get another read lock on the same resource will throw an exception

 the answer is:
    b.    A thread which has a read lock on a resource may not acquire a write lock on the same resource       

 Question25:
Which of the following conditions can trigger the automatic recycling of an ASP.NET application hosted in IIS?


    a.    A specific number of requests to the application process.
    b.    A percentage of physical memory utilized by the process.
    c.    A specific time interval
    d.    All of the above

 the answer is:
    d.    All of the above       

 Question26:
Which of the following is not a characteristic, that a Query expression should have?


    a.    It must contain a from clause
    b.    It must begin with a select clause
    c.    It can end with a group clause

 the answer is:
    b.    It must begin with a select clause       

 Question27:
When using asynchronous partial updates with an UpdatePanel, which of the following are true?


    a.    Only the UpdatePanel and any child controls go through the server lifecycle.
    b.    The entire page always goes through the entire lifecycle.
    c.    Only the UpdatePanel which initiated the Postback and its child controls can provide updated information.
    d.    UpdatePanels can not be used with Master Pages.

 the answer is:
    d.    UpdatePanels can not be used with Master Pages.       

 Question28:
Which of the following statements is false about Passport Authentication?


    a.    The Passport SDK must be installed.
    b.    Passport authentication requires a network path between the Client and the Microsoft Passport Server
    c.    Passport Authentication provides persistent authentication across sessions

 the answer is:
    b.    Passport authentication requires a network path between the Client and the Microsoft Passport Server       

 Question29:
The default number of threads per processor in the System.Threading.ThreadPool class under version 3.5 of the Framwork is:


    a.    1
    b.    25
    c.    250
    d.    100
    e.    500

 the answer is:
    d.    100       

 Question30:
Which of the following statements do Expression Trees fit best?


    a.    Expression trees are a data structure which can be initially composed using language syntax.
    b.    Expression trees are a dynamically generated code which is executed to perform the desired function.
    c.    Expression trees can be modified once they are created

 the answer is:
    c.    Expression trees can be modified once they are created       

 Question31:
Which of the following are performed to fully debug an ASP.NET Application running on the same machine as the debugger?


    a.    Enabling debug information in the .NET Assembly
    b.    Setting the debug attribute of the compilation element to true in the web.config file.
    c.    Enabling ASP.NET debugging in the IIS metabase.

 the answer is:
    c.    Enabling ASP.NET debugging in the IIS metabase.       

 Question32:
Which of the following are included in the advantages of Lambda Expressions over Anonymous methods?


    a.    More concise syntax
    b.    The types for a Lambda Expression may be omitted
    c.    The body of an Anonymous method can not be an expression
    d.    Lambda Expressions permit deferred type inference, that anonymous methods do not
    e.    All of the above

 the answer is:
    b.    The types for a Lambda Expression may be omitted       

 Question33:
Which of the following controls allows the use of XSL to transform XML content into formatted content?


    a.    System.Web.UI.WebControls.Xml
    b.    System.Web.UI.WebControls.Xslt
    c.    System.Web.UI.WebControls.Substitution
    d.    System.Web.UI.WebControls.Transform

 the answer is:
    d.    System.Web.UI.WebControls.Transform       

 Question34:
Which of the following is not an unboxing conversion?


    a.    void Sample1(object o)
{
   int i = (int)o;
}
    b.    void Sample1(ValueType vt)
{
   int i = (int)vt;
}
    c.    enum E { Hello, World}

void Sample1(System.Enum et)
{
   E e = (E) et;
}
    d.    class C { public int Value { get; set; } }

void Sample1(C vt)
{
   int i = vt.Value;
}

 the answer is:
    d.    class C { public int Value { get; set; } }

void Sample1(C vt)
{
       

 Question35:
Which of the following are true about Nullable types?


    a.    A Nullable type is a reference type.
    b.    An implicit conversion exists from any non-nullable value type to a nullable form of that type.
    c.    A predefined conversion from the nullable type S? to the nullable type T? exists if there is a predefined conversion from the non-nullable type S to the non-nullable type T

 the answer is:
    c.    A predefined conversion from the nullable type S? to the nullable type T? exists if there is a predefined conversion from the non-nullable type S to the non-nullable type T       

 Question36:
Which of the following are required to be true by objects which are going to be used as keys in a System.Collections.HashTable?


    a.    They must handle case-sensitivity identically in both the GetHashCode() and Equals() methods.
    b.    Key objects must be immutable for the duration they are used within a HashTable.
    c.    Get HashCode() must be overridden to provide the same result, given the same parameters, regardless of reference equality unless the HashTable constructor is provided with an IEqualityComparer parameter.
    d.    Each Element in a HashTable is stored as a Key/Value pair of the type System.Collections.DictionaryElement
    e.    All of the above

 the answer is:
    d.    Each Element in a HashTable is stored as a Key/Value pair of the type System.Collections.DictionaryElement       

 Question37:
Where should information about a control created at design time be stored?


    a.    ApplicationState
    b.    SessionState
    c.    ViewState
    d.    None of the above

 the answer is:
    d.    None of the above       

 Question38:
Which directive allows the utilization of  a custom web control in an ASP.NET page?


    a.    @Register
    b.    @Include
    c.    @Control
    d.    @Import

 the answer is:
    d.    @Import       

 Question39:
The output generated by the following code will be:

string t = @"This\Is\a\Test";
Response.Write(t);


    a.    ThisIsaTest
    b.    This\Is\a\Test
    c.    It will give a compilation error: Unrecognized escape sequence

 the answer is:
    c.    It will give a compilation error: Unrecognized escape sequence       

 Question40:
Which of the following events should be used for assigning a Theme dynamically to a page?


    a.    PreInit
    b.    Init
    c.    PreLoad
    d.    PreRender
    e.    Render

 the answer is:
    c.    PreLoad

Source

oDesk Test#02

Posted by imomins on September 8, 2012 at 5:25 AM Comments comments (0)

[তারাতারি উত্তর পত্র মেলানোর নিয়মঃ এক মজিলার এক ট্যাবে ওডেক্স এর পরীক্ষা আর অন্য ট্যাবে এই উত্তর পত্র রেখে  Ctrl+F চাপেন তাহলে ফাইন্ড বক্স আসবে প্রশ্নের কিছু অংশ লিখে পাশের ট্যাবে ফাইন্ড দিন পেয়ে যাবেন । ফাইন্ড নেক্সট দিয়ে যাচাই করতে পারেন]

01. Q: Which of the following actions are NOT allowed when applying to job openings?

A: All of the above.

 

02. Q: Which of the following is TRUE about fixed-price contracts?

A: How much to pay and when to pay is at the employer's discretion.

 

03. Q: Which of the following are required to qualify for guaranteed payment?

A: All of the above.

 

04. Q: Which of the following are TRUE about the oDesk dispute process?

A: All of the above.

 

05. Q: Which of the following statements about oDesk fees is FALSE?

A: The oDesk fee is $2/hour for hourly contracts.

 

06. Q: Which of the following is FALSE about weekly limits on hourly contracts?

A: The weekly limit can be changed by the contractor.

 

07. Q: What happens when a contract ends?

A: All of the above.

 

08. Q:  The oDesk Team application Time Tracker records which of the following?

A: All of the above.

 

09. Q: Which of the following are TRUE about your oDesk Work Diary?

A: All of the above.

 

10. Q: Can I start my own agency on oDesk?

A:  Yes! You can create an agency and earn money by selling the services of your agency contractors.

 

11. Q: Which of the following are NOT permitted on oDesk?

A: All of the above.

 

12. Q: Which of the following actions are NOT allowed when applying to job postings?

A: All of the above.

 

13. Q: Can I start my own company on oDesk?

A: Yes! oDesk allows you to build and manage a team of workers, colleagues and collaborators. You can even subcontract other workers on oDesk to other customers oDesk (and take a cut).

 

14. Q: ‘How does feedback work on oDesk?’

A: All of the above.

 

15. Q: Which of the following is true of your oDesk timelog?

A: All of the above

 

16. Q: Which of the following break the oDesk user agreement?

A: All of the above.

 

17. Q: Which of the following statements about the oDesk Team application are true?

A: All of the above.

 

18. Q: What do you need to do to ensure guaranteed payment on hourly jobs?

A: All of the above.

 

19. Q: If you have not done so please download and install the oDesk Team application. With the client running right click on the oDesk Team icon in the system tray (or doc for Mac users). Which of the following options is listed first? Note that you do NOT have to log into any actual Team Room to answer this question.

A: TeamRoom.

 

20. Q: Which of the following statements are correct about oDesk fees?

A: All of the above.

 

21. Q: Buyers set weekly limits on hourly assignments, how do these work?

A: All of the above.

 

22. Q: How does oDesk’s dispute resolution policy for work?

A: All of the above.

 

23. Q: Staffing managers can apply to jobs for you.

A: True.

 

24. Q: Which of the following statements is FALSE about oDesk agencies?

A: Payments made to agency contractors are automatically split by oDesk between the agency and the contractor.

ভালো থাকবেন সবাই । দোয়া রাখবেন আমার জন্য ।

oDesk Test#01

Posted by imomins on September 8, 2012 at 5:25 AM Comments comments (0)

ওডেস্ক রেডিনেস টেষ্টের প্রশ্নের উত্তর-জুলাই/2012 1.  Which of the following are NOT permitted on oDesk?

 
a. Sharing a single account between multiple people
b. Opening more than one account on oDesk
c. Using a logo or clip art as your profile portrait
d. Using a fake name

  e. All of the above (ANS)

 2.  Which of the following actions are NOT allowed when applying   to job postings? 

 a. Misrepresenting your skills, experiences, portfolio, etc.
  b. Submitting boilerplate, placeholder or generic bids or other spam
  c. Disclosing direct contact information
  d. Applying when you are not truly qualified
 e. All of the above (ANS)
  3. Can I start my own agency on oDesk?
 a. Yes! You can create an agency and earn money by selling the services of your     agency contractors.(ANS)
  b. No, oDesk is for independent contractors only
 4. What happens when a contract ends?
  a. You lose access to the Work Diary
  b. Both users can leave feedback
  c. The feedback system is double blind, so your employer cannot see the feedback you
  left them until after they have left feedback for you
 d. Hours will be billed (and disputes may be filed) according to the usual weekly payment       schedule
  e. ALL of the above(ANS)
  5. Which of the following are TRUE about your oDesk Work Diary?
  a. Allows employers to see when and what their contractors are working on
  b. Enables automatic billing for hourly contracts
  c. The oDesk Team application auto-tracks time which can be reviewed in the Work Diary
  d. Manual time can be added, but isn't guaranteed payment
e. ALL Of the above(ANS)
  6. Which of the following are TRUE about the oDesk dispute process?
  a. The dispute process only applies to Hourly contracts
  b. If you fail to respond, oDesk will refund the employer and suspend your account
  c. If you reject the dispute, oDesk specialists will review your Work Diary and
  evaluate it against the criteria of the payment guarantee
  d. Disputed hours ruled in the employers favor are refunded
e. ALL of the above(ANS)
 7.  Which of the following is FALSE about weekly limits on hourly contracts?
  a. Hours in excess of the weekly limit will not be billed to the employer
  b. You should discuss any need to work beyond your limit with your employer
c. The weekly limit can be changed by the contractor(ANS)
  d. The weekly limit can be changed by the employer
  e. Hours in excess of the weekly limit are not guaranteed payment
  8. The oDesk Team application Time Tracker records which of the following
  a. Screenshot of the active screen once per billing segment
  b. Number of keystrokes
  c. Number of mouse clicks
  d. Memo entered by the contractor
e. All of the above(ANS)
 9. Which of the following statements about oDesk fees is FALSE?
  a. The oDesk fee is 10% of the employer's payment to oDesk
  b. ODesk is free to join
  c. ODesk is free for contractors to apply and work on jobs
d. The ODesk fee is $2/hour for hourly contracts  (ANS)
  e. All of the above
 10. Which of the following is TRUE about fixed-price contracts?
  a. Employer billed automatically each week
b. How much to pay and when to pay is at the employer's discretion(ANS)
  c. Hours worked will show on your profile
  d. Time-tracking required
  e. Qualify for the oDesk payment guarantee
 11. Which of the following are required to qualified for guaranteed payment.
  a. An hourly contract.
  b. Tracking your time with the oDesk team application.
  c. Entering relevant memos.
  d. An employer with a verified payment methods.
  e. All of the above (ANS) 

MVC

Posted by imomins on August 26, 2012 at 2:45 PM Comments comments (0)

ASP.NET MVC is not all about Linq to SQL

 

Pretty much every sample application that illustrates ASP.NET MVC uses Linq To SQL or the Entity Framework as the data access method. I've seen a number of questions posted to the forums at www.asp.net asking if there are any alternatives, and indeed there are. This article will look at using plain ADO.NET within a data access layer to provide dynamic content to a typical small CRUD application.

 

For the purposes of this exercise, I shall be borrowing heavily from Imar Spaanjaar's N-Layer design article series presented here: Building Layered Web Applications with Microsoft ASP.NET 2.0. I would strongly recommend that you read the series of articles, or at least the first two to familiarise yourself with the basics of an N-Layer approach to ASP.NET application design. 3 key layers from that application: Business Objects, Business Logic and Data Access will be included in the following MVC application with little or no change at all, and the article series provides excellent detail on how the layers are constructed. This article will look at what role they play, but will not delve into their code in any real detail.

First we take a look at the application as presented by Imar. It's a simple one that typifies CRUD operations. It allows the user to manage Contacts, along with their addresses, telephone numbers and email addresses. It features the ability to Create, Read, Update and Delete any of the entities.

The Entities associated with the application are ContactPersons, PhoneNumbers, Addresses and EmailAddresses. They all live in the Business Objects (BO) layer of the application. Each of these classes contain public properties with getter and setter methods in the original sample. They do not feature any behaviour, which is housed within the Business Logic Layer (BLL) in entitynameManager classes.  There's a one-to-one mapping between an Entity and its associated Manager class. Each of the manager classes contain methods that retrieve an instance of an entity, a collection of entities, to save an entity (update or add) and to delete an entity. This area of the application can also be used to apply validation, security etc, but that is not included in the sample so that it isn't too cluttered. If you would like to see validation etc in action within the BLL, have a look at Imar's 6 part series that features updates to the application including moving it to version 3.5 of the ASP.NET framework.

The final layer is the Data Access Layer (DAL). This layer also features classes that have a one to one mapping with the Manager classes in the BLL. The methods within the BLL actually call related methods in the DAL. The DAL methods are the only ones in the application that know what mechanism is used to persist (store) entities. In this case, it's a SQL Server Express database, so this set of classes makes use of ADO.NET and the SqlClient classes. The idea behind this approach is that if you need to swap your persistence mechanism (to use XML or Oracle, for example, or to call Web Services, or even to use Linq To SQL or another ORM), you only need to replace the DAL. So long as the new DAL exposes methods containing the same signature as those called from the BLL, everything should continue to work without having to change other areas of the application. Ensuring that any new DAL adheres to the existing method signatures can be achieved through the use of Interfaces, but that would be the topic of a future article... perhaps.

MVC Architecture

There are plenty of good articles that discuss the architecture of MVC applications, so this one will not go into serious detail. For a deeper look, I recommend visiting the Learn section of Microsoft's official ASP.NET MVC site. Briefly, though, the M is for Model, which is where the BO, BLL and DAL will live. The V is for View, which is essentially any UI-related development - or what the user sees, and the C is for Controller. Controllers co-ordinate the applications responses to requests made by users. If a user clicks a button that points to a specific URL, that request is mapped to a Controller Action (class method) that will be responsible for handle any logic required to service the request, and returning a response - typically a new View, or an update to the existing View.

Having created a new MVC application within Visual Studio and removed the default Views, and Controllers, the first thing I did  was to copy the BO, BLL and DAL files from Imar's application to the Model area of my new app. I also copied the Sql Server database file from App_Data in the original site, into the same place within the MVC application, and did the same with the Style.css file, which was copied into the MVC Content folder.

I made a few other modifications. The database connection string needed to be added to the MVC application's Web.Config file. In addition, I made couple of changes to the Namespaces within the copied class files, and updated some of the DAL code to C# 3.0, although neither of these amendments are strictly necessary. Once I had done that, I hit Ctrl + Shift + F5 to ensure that the project compiled. I will not need to revisit these files at all from now on, except for some DAL methods and their associated BLL methods, as will be covered later.

Controllers

I added four controllers (having removed the default ones provided by Visual Studio) - one for each Entity. These are ContactController, PhoneController, AddressController and EmailController.

Each of the controllers will be responsible for coordinating 4 actions - List, Add, Edit and Delete. So the first thing I will do is register the Route for these actions within Global.asax:

public static void RegisterRoutes(RouteCollection routes)
{
  routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

  routes.MapRoute(
      "Default",                                              
      "{controller}/{action}/{id}",                           
      new { controller = "Contact", action = "List", id = "" }  
  );
}

The default view for the application will be listing the contacts. Contact data is obtained by the existing GetList() method within the ContactPersonManager class in the BLL, so the code for the List() action is as follows:

public ActionResult List()
{
  var model = ContactPersonManager.GetList();
  return View(model);
}

Strongly Typed Views

I'm going to use strongly typed Views throughout the application because they provide for intellisense in the Views and don't rely on ViewData indexing by string, which is prone to errors. To tidy things up as I go on, I have added some namespaces (the ones below the default ones in bold) to the web.config <namespaces> section. These are the ones I used to replace the existing namespaces in Imar's code:

    

<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Ajax"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
<add namespace="System.Linq"/>
<add namespace="System.Collections.Generic"/>
<add namespace="ContactManagerMVC.Views.ViewModels"/>
<add namespace="ContactManagerMVC.Models.BusinessObject"/>
<add namespace="ContactManagerMVC.Models.BusinessObject.Collections"/>
<add namespace="ContactManagerMVC.Models.BusinessLogic"/>
<add namespace="ContactManagerMVC.Models.DataAccess"/>
<add namespace="ContactManagerMVC.Models.Enums"/>
</namespaces>

This means they are available to all of the application and I don't need to fully qualify types within the Views. The type returned by the GetList() method is a ContactPersonList, which is set up in the Collections folder within the BO layer. It is simply a collection of ContactPerson objects. The Page declaration at the top of the List view is as follows:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 
    Inherits="System.Web.Mvc.ViewPage<ContactPersonList>" %>


You will also notice that I have included a MasterPage. Within the MasterPage, I have referenced the css file from Imar's sample code. The markup that manages the display of ContactPerson objects is as follows:

  

<table class="table">
    <tr>
      <th scope="col">Id</th>
      <th scope="col">Full Name</th>
      <th scope="col">Date of Birth</th>
      <th scope="col">Type</th>
      <th scope="col">&nbsp;</th>
      <th scope="col">&nbsp;</th>
      <th scope="col">&nbsp;</th>
      <th scope="col">&nbsp;</th>
      <th scope="col">&nbsp;</th>  
    </tr>
    <%
      if (Model != null)
      {
        foreach (var person in Model)
        {%>
    <tr>
      <td><%= person.Id %></td>
      <td><%= person.FullName %></td>
      <td><%= person.DateOfBirth.ToString("d") %></td>
      <td><%= person.Type %></td>
      <td title="address/list" class="link">Addresses</td>
      <td title="email/list" class="link">Email</td>
      <td title="phone/list" class="link">Phone Numbers</td>
      <td title="contact/edit" class="link">Edit</td>
      <td title="contact/delete" class="link">Delete</td>
    </tr>
    <%
        }
      }else{%>
    <tr>
      <td colspan="9">No Contacts Yet</td>
    </tr>  
     <% }%>
  </table>

You can immediately see the benefit of strong typing in the view. The Model is of type ContactPersonList, so each item is a ContactPerson and their properties are available without having to cast the Model to ContactPersonList. Incorrect casting is only detected at runtime, which can be inconvenient to say the least.

I cheated a little with the html. I could have selected "List" from the View Content option when generating the View, which would have provided some default templated html. I didn't. I wanted something that would work with Imar's css more easily, so I ran his application on my machine and once it was in the browser, Viewed Source and copied the rendered html from that. Imar uses GridViews in his web forms application, so a bit of css etc is automatically embedded within the source when they are rendered. I cleaned that up and moved the table styling to a css class called table over to the css file. I also added some additional styles for the <th> and <td> elements. You can see them in the accompanying download.

I also added some title attributes to some of the table cells. These are the ones that contain the links to other actions within the original application. I decided that I did not want the whole page to post back when addresses or phone numbers are viewed, or when the user wants to edit or delete existing records. I wanted the site to be Ajax-enabled. These title attributes play a key role in the Ajax (provided by jQuery) that feature in my version. The "link" css class makes text behave like a hyperlink, in that it is underlined and the cursor turns to a pointer (hand) onmouseover.

jQuery AJAX

Before looking at the main bulk of the script that manages Ajax functionality, here are three more lines of html that are added to the bottom of the List view:

<input type="button" id="addContact" name="addContact" value="Add Contact" />
<div id="details"></div>
<div id="dialog" title="Confirmation Required">Are you sure about this?</div>

The first is the button that allows users to add new contacts. The second is an empty div which is waiting for content and the third is part of the jQuery modal confirmation box that prompts users to confirm that they want to delete a record.

3 files in the Master page. One is the main jQuery file, and the other two are from the jQuery.Ui library. These are sued for a modal dialog and for a date picker:

<script src="../../Scripts/jquery-1.3.2.min.js" type="text/javascript"></script>
<script src="../../Scripts/ui.core.min.js" type="text/javascript"></script>
<script src="../../Scripts/jquery-ui.min.js" type="text/javascript"></script>

Here's the complete jQuery for the List view preceded by what the rendered view looks like:

<script type="text/javascript">
  $(function() {
    // row colours
    $('tr:even').css('background-color', '#EFF3FB');
    $('tr:odd').css('background-color', '#FFFFFF');
    // selected row managment
    $('tr').click(function() {
      $('tr').each(function() {
        $(this).removeClass('SelectedRowStyle');
      });
      $(this).addClass('SelectedRowStyle');
    }); 
    // hide the dialog div
    $('#dialog').hide();
    // set up ajax to prevent caching of results in IE
    $.ajaxSetup({ cache: false });
    // add an onclick handler to items with the "link" css class
    $('.link').live('click', function(event) {
      var id = $.trim($('td:first', $(this).parents('tr')).text());
      var loc = $(this).attr('title');
      // check to ensure the link is not a delete link
      if (loc.lastIndexOf('delete') == -1) {
        $.get(loc + '/' + id, function(data) {
          $('#details').html(data);
        });
      // if it is, show the modal dialog   
      } else {
        $('#dialog').dialog({
          buttons: {
            'Confirm': function() {
              window.location.href = loc + '/' + id;
            },
            'Cancel': function() {
              $(this).dialog('close');
            }
          }
        }); 
        $('#dialog').dialog('open');
        }
      }); 
      // add an onclick event handler to the add contact button
      $('#addContact').click(function() {
        $.get('Contact/Add', function(data) {
          $('#details').html(data);
        });
      }); 
    });
</script>

This may look daunting, but as with all things jQuery, it is simple, and I have broken down the various parts through the use of comments to make it easier to follow. The first thing that the script does is to replace the AlternatingRowColor management that web forms provides on the server to data presentation controls. It applies css styling to rows once the table has been rendered. Then I have added some additional code to cater for the fact that Imar's original sample includes a way of highlighting the currently selected row. Then I have added one line to prevent IE caching results. If you don't do this, you will scratch your head wondering why edits and deletes do not show up in the browser while the records have clearly been changed in the database.

The next bit is interesting. It makes use of the .live()  method, which ensures that event handlers are attached to all matching elements, whether they exist at the moment or not. When the user clicks an Addresses link for example, the result is another table listing the related phone numbers:

You can see that the table contains Edit and Delete links. If I didn't use .live(), these would not have event handlers attached. The event handler is attached to the click event of the cells decorated with the "link" class. It first obtains a value for the id of the record. In the case of the Contact Person table, that will be the ContactPersonId (it's the content of the first cell in the table row). In sub forms, it will be the id of the phone number or email address. These are needed when passed to the controller action responsible for editing, deleting or displaying. More of that later.

 You should also now see why I have added title attributes to the table cells. They contain the route that needs to be invoked, and the full url is constructed by appending the id to the route. Next, a check is made to see if the route contains the word "delete". If not, a request is fired and the result is displayed in the details div. If it is a delete link, the modal confirmation box is invoked before the record is deleted, giving the user the option to change their mind. See? I said it was simple!

Finally an event handler is attached to the click event of the Add Contact button. We will have a look at this part next.

Adding Contacts and Custom View Models

When adding a record within an ASP.NET application, the customary practice is to present the user with a form containing a series of inputs via which they can supply values. Most of the inputs for a ContactPerson object are straightforward: first name, last name, date of birth. One of them is not so straightforward - Type. This value must be drawn from the enumeration defined within PersonType.cs (Friend, Colleague etc) in the enums folder within the Model. This means that we must present the user with a restricted selection of valid values. A DropDownList will do the job. However, a series of optional values forms no part of the existing ContactPerson object, so we need to present a customised version of the ContactPerson to the view to accommodate this. This is where customised View Models come in.

I've read some debate on where View Models should be placed within an application. Some people feel they are part of the model. My opinion is that they are related to views. They are only really relevant to MVC applications, and are not really reusable, so they should not go into the model. For that reason, I choose to create a ViewModels folder and add that under the Views folder.  To that, I add a ContactPersonViewModel.cs file with the following code:

using System;
using System.Collections.Generic;
using System.Web.Mvc;

namespace ContactManagerMVC.Views.ViewModels
{
  public class ContactPersonViewModel
  {
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
    public IEnumerable<SelectListItem> Type { get; set; }
  }
}

Looking at the last property, you can see that I have made Type a collection of IEnumerable<SelectListItem>. This will be bound to the Html.DropDownList in the view.

There are two actions for adding within the controller. The first is decorated with the AcceptVerbs(HttpVerbs.Get) attribute while the second is marked with the AcceptVerbs(HttpVerbs.Post) attribute. The first is responsible for passing back a data entry form and the second handles the values that are posted when the form is submitted:

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Add()
{
  var personTypes = Enum.GetValues(typeof (PersonType))
    .Cast<PersonType>()
    .Select(p => new
                   {
                     ID = p, Name = p.ToString()
                   });
  var model = new ContactPersonViewModel
                {
                  Type = new SelectList(personTypes, "ID", "Name")
                };
  return PartialView(model);
}


[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Add(ContactPerson person)
{
  ContactPersonManager.Save(person);
  return RedirectToAction("List");
}

The first few lines in the first action are responsible for transferring the values in the ContactType enumeration to an array, each item of which is then cast to an anonymous object having an ID property and a Name property. The ID is the enumeration value, and the Name is the constant value that goes with the enumeration. A ContactPersonViewModel object is instantiated, and the Type property has the IEnumerable of anonymous objects passed in to a SelectList object along with the data value values, and the data text values. I used a Partial View for adding a contact, selecting the strongly-typed option again and choosing ContactPersonViewModel for the type. The code for the partial follows:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ContactPersonViewModel>" %>

<script type="text/javascript">
  $(function() {
  $('#DateOfBirth').datepicker({ dateFormat: 'yy/mm/dd' });
  });
</script>

<% using (Html.BeginForm("Add", "Contact", FormMethod.Post)) {%>
      <table>
        <tr>
          <td class="LabelCell">Name</td>
          <td><%= Html.TextBox("FirstName") %></td>
        </tr>
        <tr>
          <td class="LabelCell">Middle Name</td>
          <td><%= Html.TextBox("MiddleName") %></td>
        </tr>
        <tr>v
          <td class="LabelCell">Last Name</td>
          <td><%= Html.TextBox("LastName") %></td>
        </tr>
        <tr>
          <td class="LabelCell">Date of Birth</td>
          <td><%= Html.TextBox("DateOfBirth", String.Empty)%></td>
        </tr>
        <tr>
          <td class="LabelCell">Type</td>
          <td><%=Html.DropDownList("Type")%>
          </td>
        </tr>
        <tr>
          <td class="LabelCell"></td>
          <td><input type="submit" name="submit" id="submit" value="Save" /></td>
        </tr>
      </table>
<% } %>

The jQuery at the top attaches a jQuery UI date picker (calendar) to the DateOfBirth textbox. The second argument passed in to the Html Helper for the DateOfBirth text box ensures that by default, the value is empty. Otherwise, all the inputs are given the same name as the corresponding ContactPerson property we want to populate. This is to ensure that the default model binder works for us without any unnecessary messing around. The enum for ContactType is also bound automatically for us by MVC:

The method that responds to POST requests is then able to match the incoming Request.Form values to properties on a ContactPerson object, and then call the associated BLL Save() method with minimum code. This is followed by the page refreshing in response to a RedirectToAction call to the List action.

Editing a ContactPerson

Again, there are two actions on the controller for editing: one for the initial GET request and another for the POST submission:

[AcceptVerbs(HttpVerbs.Get)]
    public ActionResult Edit(int id)
    {
      var personTypes = Enum.GetValues(typeof (PersonType))
        .Cast<PersonType>()
        .Select(p => new { ID = p, Name = p.ToString() });

      var contactPerson = ContactPersonManager.GetItem(id);
      var model = new ContactPersonViewModel
                    { 
                      Id = id,
                      FirstName = contactPerson.FirstName,
                      MiddleName = contactPerson.MiddleName,
                      LastName = contactPerson.LastName,
                      DateOfBirth = contactPerson.DateOfBirth,
                      Type = new SelectList(personTypes, "ID", "Name", contactPerson.Type)
                    };
      return PartialView(model);
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(ContactPerson person)
    {
      ContactPersonManager.Save(person);
      return RedirectToAction("List");
    }

We've already seen how jQuery is used to invoke the Edit action passing the ID of the person to be edited. That id is used to retrieve the person details from the database through the now familiar route of BLL calling DAL methods. The ContactPersonViewModel is constructed form the returned data, with the addition of the SelectList as in the Add method. This time though, the SelectList constructor features a third parameter, which is the actual Type for this person. The third argument in the constructor is the selected value.

The partial view code is again almost identical to the Add view:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ContactPersonViewModel>" %>

<script type="text/javascript">
  $(function() {
    $('#DateOfBirth').datepicker({dateFormat: 'yy/mm/dd'});
  });
</script>

<% using (Html.BeginForm("Edit", "Contact", FormMethod.Post)) {%> 
     <table>
        <tr>
          <td class="LabelCell">Name</td>
          <td><%= Html.TextBox("FirstName") %></td>
        </tr>
        <tr>
          <td class="LabelCell">Middle Name</td>
          <td><%= Html.TextBox("MiddleName") %></td>
        </tr>
        <tr>
          <td class="LabelCell">Last Name</td>
          <td><%= Html.TextBox("LastName") %></td>
        </tr>
        <tr>
          <td class="LabelCell">Date of Birth</td>
          <td><%= Html.TextBox("DateOfBirth", Model.DateOfBirth.ToString("yyyy/MM/dd")) %></td>
        </tr>
        <tr>
          <td class="LabelCell">Type</td>
          <td><%= Html.DropDownList("Type")%></td>
        </tr>
        <tr>
          <td class="LabelCell"><%= Html.Hidden("Id") %></td>
          <td><input type="submit" name="submit" id="submit" value="Save" /></td>
        </tr>
      </table>
<% } %>

The key differences are that the DateOfBirth field now contains a format string for displaying the date in a friendly way. Added to that is the Html.Hidden() helper near the submit button, which has the value of the person being edited. Oh, and of course the form is targeted at a different action to the Add form. There is an argument possibly for combining the Add and Edit forms and action, and using a token to detect the mode that the form is in (Add or Edit) to conditionally set some of the markup in a combined partial view, and to control the code within the combined action. It would reduce a fair amount of repetition. I have separated them out in this sample for the sake of clarity primarily.

Deleting a ContactPerson

The delete action is straightforward, and there is no View associated wtih it. There doesn't need to be. Just going back to the List action will refresh the data:

public ActionResult Delete(int id)
{
  ContactPersonManager.Delete(id);
  return RedirectToAction("List");
}

This is where I chose to make a change to the original BLL and DAL. The original ContactPersonManager.Delete() method takes an instance of the person to be deleted. Within the DAL Delete() method, only the id of the person is referenced (or needed). I see no point in passing in whole objects when you are referencing them by their unique id, so I amended the methods to accept an int. It also makes the code easier, as I would otherwise have to instantiate the ContactPerson object just to get rid of it.

The jQuery invokes the confirmation modal dialog when a Delete link is clicked.

If the Cancel button is clicked, nothing happens (apart from the modal closing). If the Confirm button is clicked, the url that was constructed from the jquery is invoked pointing to the delete action.

Managing the Collections

All of the collections - PhoneNumberList, EmailAddressList and AddressList are managed in exactly the same way as eachother. Consequently, I shall just pick one (EmailAddressList) to illustrate the methodology. You can examine the download to see exactly how the others work.

First, we will look at displaying the Email Addresses associated with the selected ContactPerson. This involves a List action on the controller:

public ActionResult List(int id)
{
  var model = new EmailAddressListViewModel
                {
                  EmailAddresses = EmailAddressManager.GetList(id),
                  ContactPersonId = id
                };
  return PartialView(model);
}

The method takes the id of the contact (from the first cell in the row that's been clicked, if you remember) and returns another custom view model - EmailAddressListViewModel. This is so that the Id of the contact person can be passed in to the View:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<EmailAddressListViewModel>" %>
<script type="text/javascript">
  $(function() {
    $('#add').click(function() {
      $.get('Email/Add/<%= Model.ContactPersonId %>', function(data) {
        $('#details').html(data);
      });
    });
  });
</script>
<table class="table">
   <tr>
     <th scope="col">Contact Person Id</th>
     <th scope="col">Email</th>
     <th scope="col">Type</th>
     <th scope="col">&nbsp;</th>
     <th scope="col">&nbsp;</th>
   </tr>
   <%if(Model.EmailAddresses != null)
     {foreach (var email in Model.EmailAddresses) {%>
   <tr>
     <td><%= email.Id %></td>
     <td><%= email.Email %></td>
     <td><%= email.Type %></td>
     <td title="email/edit" class="link">Edit</td>
     <td title="email/delete" class="link">Delete</td>
   </tr>
        <%}
    }else
 {%>
   <tr>
     <td colspan="9">No email addresses for this contact</td>
   </tr>
 <%}%>
</table>
<input type="button" name="add" value="Add Email" id="add" />

You can see that the ContactPersonId is needed for the Add method. We need to make sure we are adding a new item to the correct contact's collection. Otherwise the Edit and Delete methods work in exactly the same was as for the ContactPerson itself - the id of the item to be amended or deleted is passed in via the URL, and the table cells are set up with a title attribute so that they can take advantage of the .live() method that was deployed earlier in the List view for the contacts.

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Add(int id)
{
  var contactTypes = Enum.GetValues(typeof(ContactType))
    .Cast<ContactType>()
    .Select(c => new
    {
      Id = c,
      Name = c.ToString()
    });
  var model = new EmailAddressViewModel
                {
                  ContactPersonId = id,
                  Type = new SelectList(contactTypes, "ID", "Name")
                };
  return PartialView("Add", model);
}


[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Add(EmailAddress emailAddress)
{
  emailAddress.Id = -1;
  EmailAddressManager.Save(emailAddress);
  return RedirectToAction("List", new {id = emailAddress.ContactPersonId});
}

A custom View Model has been created for this purpose of displaying existing EmailAddress objects for editing and adding. This includes the same kind of property for binding an IEnumerable<SelectListItem> collection for the Type dropdown. Where these methods differ from their ContactController counterparts is in what they return. The first returns the Add form as a partial, while the second Redirects to the List action on the same controller, which results in the revised collection being updated (and is also the reason why the no-cache option was set in the original Ajax).

In the case of the collection items, each one has its Id set to -1 within the action before it is saved. This is to ensure that the correct flow of code takes control in the "Upsert" stored procedure. By default at the moment, a value is picked up from the ReouteData id paramter (which is that belonging to the ContactPerson) so if it is not set


Rss_feed