ASP.NET Core 5.0 – Bearer Authentication


ASP.NET Core supports several authentication methods which are Basic, Bearer, Digest, OAuth and others. This article will show you how to build a Bearer authentication to your Web API using IAsyncAuthorizationFilter and IPolicyEvaluator interfaces.

Prerequisites

Bearer Authentication

Bearer authentication is an HTTP authentication scheme also called token authentication that involves security tokens called bearer tokens. Bearer Token is set in the Authorization header of HTTP Request.

Authorization: Bearer API Token

Why not use built in [Authorize]?

ASP.NET core official documentation does not talk about how to implement a custom Bearer Authentication. I have seen ton of samples explaining either [Authorize] or IDENTITY providers or OAUTH type authentications. However, this approach does not work on WEB API 2.0 apps which is written in .NET Full Framework.
NOTE: I’ve used IAuthenticationFilter interface to implement authentication in WEB API 2.0.

Creating ASP.NET 5.0 WEB API Project

Fire up your favorite IDE and create a brand new ASP.NET CORE Web API project template. The default template is pretty good to get started to implement Bearer token authentication method.

Project edit view

After successfully creating API project, click on edit project file and you should be able to see TargetFramework is netcoreapp5.0 and LangVersion is C# 9.0 which is in preview mode.

<PropertyGroup>
  <TargetFramework>netcoreapp5.0</TargetFramework>
  <LangVersion>Preview</LangVersion>
</PropertyGroup>

IAsyncAuthorizationFilter & IPolicyEvaluator

IAsyncAuthorizationFilter Interface – A filter that asynchronously confirms request authorization. Read more

IPolicyEvaluator Interface – Base class for authorization handlers that need to be called for a specific requirement type. Read more

Let’s implement IPolicyEvaluator interface first. The interface has two methods called AuthenticateAsync and AuthorizeAsync,

1) AuthenticateAsync method checks for Authorization header and read Bearer token from the request header.

  • Check Authorization header present in the request.
  • Read Bearer token and compare against the stored token.
  • Once token match successfully, set some Claims thus, you want to identity the request later.

2) AuthorizeAsync method does check whether the request has been already evaluated by IPolicyEvaluator and looks Succeeded or Challenged status and return Policy Authorization Result.

Below, you can find complete code for PolicyEvaluator class.

Next, implement IAsyncAuthorizationFilter interface.

OnAuthorizationAsync method calls above PolicyEvaluator API to get authentication and authorization result.

Configure services

Final step would be registering authentication interface in Startup.cs class

public void ConfigureServices(IServiceCollection services)
{
   services.AddControllers(o => o.Filters.Add(new BearerAuthorizeFilter()));
}

NOTE: Using this approach, you wouldn’t need to use any middleware like use.Authentication() or [Authorize] attribute on API controllers.

Source repository

Github – https://github.com/deepumi/aspnet-5-bearer-authentication/

Summary

In this post I described how to implement custom Bearer token in ASP.NET Core projects with out using built in Authorize mechanism.

A big thank you to Microsoft MVP Steve Gordon who recommended to use JWT tokens and built in [Authorize] mechanism for APS.NET core projects!

Hope you enjoy reading the article and please feel free to give this a try and let me know your thoughts and suggestions.

Data.Net


Data.Net

A simple, lightweight data access library for any ADO.Net providers like SQL server, Oracle & MySQL.

Source – https://github.com/deepumi/Data.Net

No Dependencies

Since Data.Net is written in .NetStandard 2.0 no third party libraries are required.

Supporting platforms

Data.Net support multiple frameworks and platforms.

  • Net Core 2.0 / ASP.NET Core 2.0
  • Net Standard 2.0
  • NetFramework 4.6.1
  • NetFramework 4.6.2
  • NetFramework 4.7.0

Nuget

Install Data.Net via Nuget

PM> Install-Package Data.Net

Execute a query and return a single value from the first row

using (var db = new Database()) //make sure connection string is configured in the config file with <connectionStrings><clear/><add../></connectionStrings>
{
  var firstName = db.ExecuteScalar<string>("SELECT FirstName From Users_Test Where Email = @Email",
                  parameters:new DataParameters{{"Email", "user@domain.com" } });
  Assert.IsTrue(!string.IsNullOrWhiteSpace(firstName));
}

Execute a query and convert to POCO object

public class User
{
    public string FirstName { get; set; } //make sure property name is same as table column name, otherwise use alias in sql query.
    public string LastName { get; set; }
    public string Email { get; set; }
}

using(var db = new Database(new OracleConnection("connectionString")))
{
    List<User> q = db.Query<User>("SELECT EmailAddress as Email,LastName FROM Users_Test");
    Assert.IsTrue(q.Count > 0);
}

Execute a stored procedure and get multiple output parameter and return value.

 var parameters = new DataParameters
 {
    { "@Email", "user1@domain.com" },
    { "@RecordCount"}, //Default parameter direction is 'output'
    { "@AnotherOutParameter"},
    { "@ReturnVal",ParameterDirection.ReturnValue}
 };

  var q = db.Query<User>("PROC_NAME", CommandType.StoredProcedure, parameters);
  
  Assert.IsTrue(q.Count > 0);
  Assert.IsTrue(dataParameter.Value<int>("@RecordCount") > 0);
  Assert.IsTrue(dataParameter.Value<int>("@AnotherOutParameter") > 0);
  Assert.IsTrue(dataParameter.Value<int>("@ReturnVal") > 0);

Execute a command with DB transaction.

using (var db = new Database())
{
  try
  {
      db.BeginTransaction(); //create transaction.
    
      db.ExecuteNonQuery("sql", parameters:new DataParameters{{"Email", "user@domain.com" } });
      db.ExecuteNonQuery("sql", parameters:new DataParameters{{"Email", "user@domain.com" } });
      
      db.CommitTransaction(); //commit transaction.
  }
  catch (Exception)
  {
      db.RollbackTransaction(); // rollback if any failure. 
  }
}

Execute multiple query using a single DB connection instance

using(var db = new Database())
{
  var reader1 = db.ExecuteReader("sql",CommandType.Text,parameters,CommandBehavior.Default);
  var reader2 = db.ExecuteReader("sql",CommandType.Text,parameters); //default behaviour is close connection
}

Create DB provider specific parameter object

Data.Net support multiple overloads so that you can create DB specific parameter object like below.

public void Add(IDbDataParameter parameter) {}  //For any Ado.Net specific provider
public void Add(string name, object value) {}
public void Add(string name, ParameterDirection direction = ParameterDirection.Output,DbType dbType = DbType.Int32, int size = 0) {}

Example usage

var p = new DataParameter();

p.Add(new OracleParameter("name","value"));
p.Add("name","value");
p.Add("name",ParameterDirection.Output,DbType.Int32,0);

Please check out more samples in the Unit test app.

Convert C# camel case json property to pascal case


I am pretty sure that many of them faced the same scenario where you would end up copy/paste some json data from a third party API sites And using one of the tools like Visual Studio IDE or json2csharp.com to generate POCO classes. However, these tools will not generate pascal case property’s automatically And if you want to maintain the coding standard you have to change the property’s to pascal case manually.

For example : Default camel case property’s generated based on Visual Studio IDE

public class Refunds
{
   public string @object { get; set; }
   public bool has_more { get; set; }
}

Since I had to convert many json property’s to pascal casing which is a tedious task so I have developed an app to convert camel case csharp json property to pascal case. http://deepumi.com/jsonproperty2TitleCase/

jsonProperty2TitleCase Core Features:

  • Convert property to Title case which is Pascal case
  • Add NewtonsoftJson property attribute to add the actual json property name for deserializing purpose.
  • Also, handles nested classes hierarchies.
  • Beautify your csharp code  (Remove all extra white spaces)

jsonProperty2TitleCase Output:

using Newtonsoft.Json;

public class Refunds
{
    [JsonProperty("object")]
    public string Object { get; set; }

    [JsonProperty("has_more")]
    public bool HasMore { get; set; }
}

http://deepumi.com/jsonproperty2TitleCase/

jsonproperty

Please feel free to give this a try and let me know your thoughts and suggestions.

http://deepumi.com/jsonproperty2TitleCase/

MadMimi.Net Integration


I have been playing around with Transaction Email Services for a while and came across the tool named MadMimi, A email marketing tool lets you to send email from a different server so that you can track whether the email delivered or bounce.

MadMimi already have a C# version API and its quite old. The reason I wrote my own version is to prevent less code change to my current project so that if I want to switch to a different provider in the feature it would be easy.

A typical email sending code

using (var message = new MailMessage())
{
    message.To.Add("receiver");
    message.From = new MailAddress("from");
    message.Subject = "Subject";
    message.Body = "This is test";
    using (var client = new SmtpClient())
    {
      client.Send(message);
    }
}

Using Library

  var mailer = new Mailer("username", "apikey");
  using (var message = new MailMessage())
  {
      message.From = new MailAddress("from email", "display name");
      message.To.Add("sender email");
      message.Subject = "Test";
      message.Body = "Email body";
      await mailer.SendAsync("Promotion Name", message);
  }
  var status = mailer.TrackStatus; //URL to track the email
  var mailTransactionId = mailer.TransactionId; //Transaction Id.

When you compare the above code snippets you should see additional two liner code which integrate the library (Mailer class) and that is the only change you should make your existing project and apps if you would like to integrate this.

Pros
SPF (
Sender Policy Framework) – MadMimi does not care if you have set up a SPF record in DNS. While most of the competitors, this is a mandatory requirement if you want to use your own “FROM” email address other than your DOMAIN.

Cons
1) Delivery speed – Some time the email take 5-6 minutes to deliver.
2) No SMTP relay support.
3) Attachment does not support via API.

Feel free to play around and fork it if you would like to make any change to this. The GitHub link is provided below for the sample project and library.

Repository – https://github.com/deepumi/MadMimi.Net

First Data Global Gateway Integration in Asp.Net MVC C#


I have added a new Github repository for First Data Global Gateway Integration in Asp.Net MVC.  The sample provides a rest api implementation for credit card based payment processing. Since, I have choosen Asp.Net MVC empty project template you might need to install System.Net.HttpClient library from nuget.org or install directly from visual studio.

Command – Install-Package Microsoft.Net.Http

Download Location or copy paste the url

https://github.com/deepumi/FirstDataPaymentGateway-CSharp.Net

This code was taken from the original source https://support.payeezy.com/hc/en-us/articles/204699865-C-REST-Sample-Code-For-Use-with-v12-v13

Example Usage:

 var paymentService = new PaymentService("1.50", "0515","Card holder name","4111111111111111", "23".ToString()); //customer Id for Internal purpose to track which customer made the transaction...
 var transactionResult = await paymenetService.PostAsync();
 if (transactionResult == null) return;
 if (transactionResult.TransactionApproved && !transactionResult.TransactionError && transactionResult.CustomerRef == customerId.ToString())
 {
 //transaction success....
 }
 else
 {
 //transaction failed
 var message = transactionResult.Message;
 }

Configuration Settings:
Following values needs to be changed in the web.config file.

<add key="GATEWAY_ID" value="Exact ID" />
<add key="GATEWAY_PWD" value="Password" />
<add key="TRANS_TYPE" value="00" />
<add key="HMAC_KEY" value="HMAC Key" />
<add key="KEY_ID" value="Key Id" />
<add key="GATEWAY_URL" value="https://api.demo.globalgatewaye4.firstdata.com" />

Transaction Summary file(transaction_summary.xml) from payment gateway is included in the App_Data folder.

Also, refer : https://support.payeezy.com/hc/en-us/articles/203731109-First-Data-Global-Gateway-e4-Web-Service-API-Reference-Guide

As per First Data knowledge base Note: “Code samples are provided “as is” and are not designed to be used in production.”

 

jQuery Autocomplete with multiple fileds in Asp.Net C#


This  article explains jQuery autocomplete with  multiple fields using Asp.Net C#.

Scenario :  Listing business titles for a specific city/state location.

Initially I used AJAX CONTROL TOOLKIT (ACT) but I ran in to many issues and finally decided to use jQuery approach which really saved my time.

You can Download the complete source code from here

Add jQuery assets on your page.

<link href="styles/jquery-ui.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="scripts/jquery.min.js"></script>
<script type="text/javascript" src="scripts/jquery-ui.min.js"></script>

jQuery Code for consuming web service.

<script type="text/javascript">
$(function () {
var search = $("#<%=txtSearch.ClientID%>");
var location = $("#<%=txtLocation.ClientID %>");
search.autocomplete({
    source: function (request, response) {
        $.ajax({
            url: '<%=ResolveUrl("~/") %>AutoCompleteService.asmx/GetKeyWords',
            data: "{ 'keyword': '" + search.val() + "', 'location' : '" + location.val() + "'}",
            dataType: "json",
            type: "POST",
            contentType: "application/json; charset=utf-8",
            dataFilter: function (data) { return data; },
            success: function (data) {
                if (data.d != null) {
                    response($.map(data.d, function (item) {
                        return {
                            value: item
                        }
                    }))
                }
            },
            error: function (XMLHttpRequest, textStatus, error) {
                //alert(textStatus);
            }
        });
    },
    minLength: 1
});

location.autocomplete({
    source: function (request, response) {
        $.ajax({
            url: '<%=ResolveUrl("~/") %>AutoCompleteService.asmx/GetLocations',
            data: "{ 'location': '" + location.val() + "'}",
            dataType: "json",
            type: "POST",
            contentType: "application/json; charset=utf-8",
            dataFilter: function (data) { return data; },
            success: function (data) {
                if (data.d != null) {
                    response($.map(data.d, function (item) {
                        return {
                            value: item
                        }
                    }))
                }
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
                // alert(textStatus);
            }
        });
    },
    minLength: 1
});

});
</script>

Code-behind for ASMX class (don’t forget to uncomment  System.Web.Script.Services.ScriptService)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Services;
using System.Collections;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService]
public class AutoCompleteService : System.Web.Services.WebService {

public AutoCompleteService () {
}

IDictionary<string, string[]> LoadItems()
{
    IDictionary<string, string[]> items = new Dictionary<string, string[]>();

    items.Add("Newyork", new string[]
                                        {
                                            "Applebee's", "Apiary", "Brenda's French Soul Food","TGI Friday's","Cafe Venue"
                                        });

    items.Add("Los Angeles", new string[]
                                        {
                                            "Los 1", "Los 2", "Los 3","TGI Friday's","Cafe Venue"
                                        });

    items.Add("Las Vegas", new string[]
                                        {
                                            "Los 1", "Los 2", "Los 3","TGI Friday's","Cafe Venue"
                                        });

    return items;
}

[WebMethod]
public string[] GetKeyWords(string keyword, string location)
{
    var items = LoadItems();
    if (items != null && items.Count > 0)
    {
        //Get all items for a specific location
        var result = (from item in items
                        where item.Key.Equals(location, StringComparison.OrdinalIgnoreCase)
                        select item.Value)
                    .FirstOrDefault();

        //check whether the items start with the keyword
        return result.Where
                            (
                                o => o.StartsWith(keyword, StringComparison.OrdinalIgnoreCase)
                            ).ToArray<string>();
    }
    return null;
}

[WebMethod]
public string[] GetLocations(string location)
{
    var items = LoadItems();
    if (items != null && items.Count > 0)
    {
        //check whether the items start with the location
        return (from item in items
                        where item.Key.StartsWith(location, StringComparison.OrdinalIgnoreCase)
                        select item.Key).ToArray<string>();

    }
    return null;
}
}

You can Download the complete source code from here

Hope this help and If you have any comments, please feel free to write your feedback.

Thanks
Deepu

 

Twitter Tweets in Asp.Net C#


I’ve been working on the twitter feed in one of my recent project where tweets getting updated on a regular interval time (say for every 30 minutes or 1 hr). I am creating this as a ASCX control so that I can reuse for multiple projects.

You can Download the complete source code from here

I am dropping a ListView control in the ASCX page which render the Twitter Profile name along with  Title, Description and Published date for the latest tweets.

Couple of properties need to configure to use this control

TwitterProfileName – Your twitter profile name or screen name

TweetsCount – No of tweets you want to return (default is 10).

<asp:ListView ID="lvTweets" runat="server">
<LayoutTemplate>
<table border="0" cellpadding="2" cellspacing="0">
<tr>
<td height="30" runat="server">
<a href="http://twitter.com/<%=<span class=&quot;hiddenSpellError&quot; pre=&quot;&quot;>TwitterProfileName</span>%>" target="_new"></a>
<%= TwitterProfileName%>
</td>
</tr>
<tr>
<td>
<asp:PlaceHolder ID="itemPlaceholder" runat="server" />
</td>
</tr>
<tr>
77B5D2;">
</td>
</tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td>
<a target="_new" href='<%# DataBinder.Eval(Container.DataItem, "Link")%>'>
<%# DataBinder.Eval(Container.DataItem, "Title")%></a>
<br />
<div>
<%# DataBinder.Eval(Container.DataItem, "PublishedDate", "{0:h:mm  tt MMM d}")%>
</td>
</tr>
</ItemTemplate>
<EmptyDataTemplate>
<div>
<h3>
No tweets available.</h3>
</div>
</EmptyDataTemplate>
<ItemSeparatorTemplate>
<tr>
1px solid lightgrey;">
</td>
</tr>
</ItemSeparatorTemplate>
</asp:ListView>
using System;
using System.Linq;
using System.Xml.Linq;
using System.Collections;
using System.Collections.Generic;

public partial class TweetsControl : System.Web.UI.UserControl
{
private static DateTime? lastUpdated = null; //holds last updated time

private static XDocument xDoc = null; //static variable to store the result xml.

//Updates latest Tweets for every 10 minutes in page refresh.
private static Double Interval = 10;

//Determine its time to get the new tweets
private static Boolean IsTimeForUpdate
{
get
{
if (lastUpdated.HasValue && DateTime.Now > lastUpdated.Value.AddMinutes(Interval))
{
return true;
}
return false;
}
}

//Hold no of tweets default set it as 10.
public Int32? TweetsCount { get; set; }

//Twitter profile name or screen name.
public String TwitterProfileName { get; set; }

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GetTweets();
}
}

private void GetTweets()
{
var xml = LoadXML();
IEnumerable query = null;
if (xml != null)
{
query = from e in xml.Descendants("item")
select new
{
Title = e.Element("title").Value,
Link = e.Element("link").Value,
PublishedDate = Convert.ToDateTime((e.Descendants("pubDate").First().Value)),
};
}
lvTweets.DataSource = query;
lvTweets.DataBind();
}

private XDocument LoadXML()
{
if (xDoc != null && !IsTimeForUpdate)
{
return xDoc;
}
else
{
try
{
TweetsCount = TweetsCount.HasValue ? TweetsCount : 10;
var url = string.Format("http://api.twitter.com/statuses/user_timeline.rss?screen_name={0}&count={1}", TwitterProfileName, TweetsCount);
xDoc = XDocument.Load(url);
lastUpdated = DateTime.Now;
return xDoc;
}
catch
{
return null;
}
}
}

}

Refer more api information on Twitter API

You can Download the complete source code from here

Hope this helps

Thanks
Deepu

using System; using System.Linq; using System.Xml.Linq; using System.Collections; using System.Collections.Generic; public partial class TweetsControl : System.Web.UI.UserControl { private static DateTime? lastUpdated = null; private static XDocument xDoc = null; private static Double Interval = 10; private static Boolean IsTimeForUpdate { get { if (lastUpdated.HasValue && DateTime.Now > lastUpdated.Value.AddMinutes(Interval)) { return true; } return false; } } public Int32? TweetsCount { get; set; } public String TwitterProfileName { get; set; } protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { GetTweets(); } } private void GetTweets() { var xml = LoadXML(); IEnumerable query = null; if (xml != null) { query = from e in xml.Descendants(“item”) select new { Title = e.Element(“title”).Value, Link = e.Element(“link”).Value, PublishedDate = Convert.ToDateTime((e.Descendants(“pubDate”).First().Value)), }; } lvTweets.DataSource = query; lvTweets.DataBind(); } private XDocument LoadXML() { if (xDoc != null && !IsTimeForUpdate) { return xDoc; } else { try { TweetsCount = TweetsCount.HasValue ? TweetsCount : 10; var url = string.Format(“http://api.twitter.com/1/statuses/user_timeline.rss?screen_name={0}&count={1}”, TwitterProfileName, TweetsCount); xDoc = XDocument.Load(url); lastUpdated = DateTime.Now; return xDoc; } catch { return null; } } } }

Google Spell Checker Api Asp.Net C#


In this article you will learn how to use the Google Spell Checker API in Asp.Net C# apps

Download the complete source code from here

The API is very simple,  spell checking is done through a XML http post to the following url

https://www.google.com/tbproxy/spell?lang=en:

Request XML structure

<?xml version=”1.0encoding=”utf-8?>
<spellrequest textalreadyclipped=”0ignoredups=”0ignoredigits=”1ignoreallcaps=”1>
<text>Hotal</text>
</spellrequest
>

The folloing are the Response XML from Google API

<?xml version=”1.0encoding=”UTF-8?>
<spellresult error=”0clipped=”0charschecked=”12>
<c o=”0l=”5s=”0″>
Hotel Hotly Total Ital Hots</c>
<
/spellresult
>

Tag Description
o The offset from the start of the text of the word
l Length of misspelled word
s Confidence of the suggestion
text Tab delimited list of suggestions

See the complete code here

using System;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;

public static class SpellChecker
{
 public static String DidYouMean(string word)
 {
 string retValue = string.Empty;
 try
 {
 string uri = "https://www.google.com/tbproxy/spell?lang=en:";
 using (WebClient webclient = new WebClient())
 {
 string postData = string.Format("<?xml version=\"1.0\" encoding=\"utf-8\" ?><spellrequest textalreadyclipped=\"0\" ignoredups=\"0\" ignoredigits=\"1\" "
 + "ignoreallcaps=\"1\"><text>{0}</text></spellrequest>",word);

 webclient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
 byte[] bytes = Encoding.ASCII.GetBytes(postData);
 byte[] response = webclient.UploadData(uri, "POST", bytes);
 string data = Encoding.ASCII.GetString(response);
 if (data != string.Empty)
 {
    retValue = Regex.Replace(data, @"<(.|\n)*?>", string.Empty).Split('\t')[0];
 }
 }
 }
 catch (Exception exp)
 {

 }
 return retValue;
 }
 }

protected void Page_Load(object sender, EventArgs e)
{
    string word = SpellChecker.DidYouMean("Hotal");
    if(word != string.Empty)
    {
         labMessage.Text = "<font style='font-size:12px;color:red;'>Did you mean </font><b>" + retValue + "</b>";
    }
}

You can Download the complete source code from here

Hope this help and If you have any comments, please feel free to write your feedback.

Thanks
Deepu

Asp.Net 4.0 URL Routing


It’s been  really easy  in Asp.Net 4.0 for building SEO friendly URL applications with VS 2010. In one my previous article I have explained how we can achieve the same in Asp.Net 3.5  (check it out).  In Asp.Net 3.5 we need to implement the IRouteHandler interface in custom route handler class and bla bla….but now in Asp.Net 4.0 we do not need all extra code.  I am following the same example in my previous article here.  In the Global.asax file I am registering the routes some thing like below

You can download the entire article from here

Global.asax file Configuration

Add Import directive to Import System.Web.Routing name space

<%@ Import Namespace=”System.Web.Routing” %>

void RegisterRoutes(RouteCollection routes)
 {
 routes.MapPageRoute(
 "member-list",
 "member/{name}",
 "~/member-list.aspx"
 );
 }

 void Application_Start(object sender, EventArgs e)
 {
RegisterRoutes(RouteTable.Routes);
}

The first parameter member/{name} which denote the url structure, here the url which starts /member/{name} (ex : /member/deepu/) will point physically to the following path ~/member/member-list.aspx

Create a aspx page called default.aspx

This page will have a list of Members in Tabular format. I am going to use asp.net List view control to achieve this.

<asp:ListView ID=”lvUserList” runat=”server”>
<LayoutTemplate>
<table width=”50%” style=”background-color: lightgrey;” cellpadding=”2″ cellspacing=”1″
border=”0″>
<tr style=”background-color: white”>
<td width=”100″ align=”center”>
Member ID
</td>
<td align=”center”>
Name
</td>
<td width=”75″ align=”center”>
Blog
</td>
<td width=”50″>
</td>
</tr>
<asp:PlaceHolder ID=”itemPlaceholder” runat=”server” />
</table>
</LayoutTemplate>
<ItemTemplate>
<tr style=”background-color: white”>
<td align=”center”>
<asp:Label ID=”lab” Text='<%# DataBinder.Eval(Container.DataItem, “MemberID”)%>’
runat=”server” />
</td>
<td>
<asp:Label ID=”Label1″ Text='<%# DataBinder.Eval(Container.DataItem, “Name”)%>’ runat=”server” />
</td>
<td align=”center”>
<a target=”_blank” href='<%# DataBinder.Eval(Container.DataItem, “BlogURL”)%>’>Blog</a>
</td>
<td align=”center”>
<a href=”<%= ResolveUrl(“~/member/”)%><%# DataBinder.Eval(Container.DataItem, “Name”)%>”>
Detail</a>
</td>
</tr>
</ItemTemplate>
<ItemSeparatorTemplate>
<br />
</ItemSeparatorTemplate>
</asp:ListView>

Default.aspx.cs code behind

public partial class Memeber
{
 public int MemberID { get; set; }
 public string Name { get; set; }
 public string BlogURL { get; set; }
}


public partial class _Default : System.Web.UI.Page
{
 protected void Page_Load(object sender, EventArgs e)
 {
 if (!IsPostBack)
 {
 BindUsers();
 }
 }

 void BindUsers()
 {
 var items = new List<Memeber>()
 {
 new Memeber {MemberID = 1,Name = "Deepu", BlogURL = "https://deepumi.wordpress.com"},
 new Memeber {MemberID = 2,Name = "Scott", BlogURL = "http://weblogs.asp.net/scottgu/"},
 new Memeber {MemberID = 3,Name = "Joe", BlogURL = "http://misfitgeek.com"},
 };


 lvUserList.DataSource = items.ToList();
 lvUserList.DataBind();
 }
}

We have completed the listing page. The next page will be the detail page which will be rendering the member name for the URL routing.

Member-List.aspx Page

<asp:Content ID=”BodyContent” runat=”server” ContentPlaceHolderID=”MainContent”>
Member Name : <asp:Label ID=”labMemberName” runat=”server” />
</asp:Content>

Member-List.aspx code behind Page

var name = Page.RouteData.Values["name"];
 if (name != null)
 {
 Page.Title = name.ToString();
 labMemberName.Text = name.ToString();
 }

You can download the entire article from here

Hope this help and If you have any comments, please feel free to write your feedback.

Thanks
Deepu

Google Map 3 with Multiple locations in Asp.Net C#


Google Map Version 3 API is especially designed to be faster and more applicable to mobile devices, as well as traditional desktop browser applications ….read more from google map api document.

Click here to download the article

If you find the Google Map 3 code library useful, please consider donating

(No more API registration key needed for Version 3.0)

In this article I am going to explain how we can show multiple locations binding from code behind dynamically (database or any data source).  Couple of moths ago in Asp.Net forum I have posted an article using Google Map Version 2.0
(http://forums.asp.net/p/1507845/3584193.aspx#3584193). Version two was kind of messy Java Script code but now in Version 3.0 Google made it very simple.

Create a ASPX page and copy paste the following markup code..

<html>
<head runat=”server”>
<meta name=”viewport” content=”initial-scale=1.0, user-scalable=no” />
<meta http-equiv=”content-type” content=”text/html; charset=UTF-8″ />
<title>Google Map 3.0</title>
<style type=”text/css”>
.formatText{color:Green;font-size:11px;font-family:Arial;font-weight:bold;}
</style>
<script type=”text/javascript” src=”http://maps.google.com/maps/api/js?sensor=false“></script>
<script type=”text/javascript”>
var map;
function initialize() {
var myLatlng = new google.maps.LatLng(40.764015, -73.982797);
var myOptions = {
zoom: 8,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}

map = new google.maps.Map(document.getElementById(“map_canvas”), myOptions);

for (var i = 0; i < locationList.length; i++) {
var args = locationList[i].split(“,”);
var location = new google.maps.LatLng(args[0], args[1])
var marker = new google.maps.Marker({
position: location,
map: map
});
var j = i + 1;
marker.setTitle(message[i].replace(/(<([^>]+)>)/ig,””));
attachSecretMessage(marker, i);
}
}

function attachSecretMessage(marker, number) {
var infowindow = new google.maps.InfoWindow(
{ content: message[number],
size: new google.maps.Size(50, 50)
});
google.maps.event.addListener(marker, ‘click’, function() {
infowindow.open(map, marker);
});
}
</script>

</head>
<body style=”margin: 0px; padding: 0px;” onload=”initialize()”>
<form runat=”server”>
<div style=”padding-top: 10%;padding-left:20%”>
<div id=”map_canvas” style=”width: 50%; height: 50%”>
</div>
</div>
</form>
</body>
</html>

I have highlighted some of the lines from the above code

1)  The class formatText, simple css class for formating the info window text. You can replace your own css style here
.formatText{color:Green;font-size:11px;font-family:Arial;font-weight:bold;}

2) In the Java Script include statement I have mention sensor=false (because the sample app is targeting on web  page if you are using from Mobile application you should  set sensor=false. Read more about mobile app)

3) In the for loop I’ m using locationList.Length. Here locationList is Java Script array object which is getting generated from an Aspx code behind page and basically the locationList object has array of  Geo code information like Latitude and Longitude. In one my previous article I have explained how we can get the Geo-code location from an address using Yahoo API.

HTML out put

var locationList = new Array( ‘40.756012, -73.972614’ , ‘40.456012, -73.796087’ , ‘40.456012, -73.456807’ );

4) Splitting lattitude and longitude from the array object and assign it to Google function like below.

var args = locationList[i].split(“,”);

var location = new google.maps.LatLng(args[0], args[1])

5)   In marker we can able to set the title value and since I am using html tags and css class I’m replacing the html tags using the following syntax

marker.setTitle(message[i].replace(/(<([^>]+)>)/ig,””));

The rest of the mark up tags are same as mentioned in the Google doc.
So now we need to create the array from code behind. Copy paste the below code in to you code behind page load method
protected void Page_Load(object sender, EventArgs e)
 {
 List<String> oGeocodeList = new List<String>
 {
 " '40.756012, -73.972614' ",
 " '40.456012, -73.796087' ",
 " '40.456012, -73.456807' "
 };

 var geocodevalues = string.Join(",", oGeocodeList.ToArray());

 List<String> oMessageList = new List<String>
 {
 " '<span class=formatText >Google Map 3 Awesome !!!</span>' ",
 " '<span class=formatText>Made it very simple</span>' ",
 " '<span class=formatText>Google Rocks</span>' "
 };

 String message = string.Join(",", oMessageList.ToArray());

 ClientScript.RegisterArrayDeclaration("locationList", geocodevalues);

 ClientScript.RegisterArrayDeclaration("message", message);
 }

The above code List<String> oGeocodeList which creates a list of Geo-Code collection object. I have hard coded latitude and longitude (you can replace with your db procedure). Once you have created the list object we should convert in to Java Script array format like below

var geocodevalues = string.Join(“,”, oGeocodeList.ToArray()); and finally register the array

ClientScript.RegisterArrayDeclaration(“locationList”, geocodevalues); here locationList is the JS array object name.

Similarly I am creating the message array for the pop window (InfoWindow)

List oMessageList = new List
{
” ‘Google Map 3 Awesome !!!‘ “,
” ‘Made it very simple‘ “,
” ‘Google Rocks‘ ”
};

String message = string.Join(“,”, oMessageList.ToArray());   //convert list object to JS array format.

ClientScript.RegisterArrayDeclaration(“message“, message); //message = JS array object name.

Please refer the following links if you need to learn more about Map API 3.0

http://code.google.com/apis/maps/documentation/v3/introduction.html
http://code.google.com/apis/maps/documentation/v3/
http://code.google.com/apis/maps/documentation/v3/reference.html

Hope this help and If you have any comments, please feel free to write your feedback.

You can download the entire article from here or copy paste the URL

http://www.4shared.com/file/251039814/3e491cfc/GoogleMap3.html

If you find the Google Map 3 code library useful, please consider donating

Thanks
Deepu