Friday, October 19, 2012

Virtual directory not being configured as an application in IIS

Virtual directory not being configured as an application in IIS

Problem

01.Configuration Error
02.Description: An error occurred during the processing of a configuration
03.file required to service this request. Please review the specific error
04.details below and modify your configuration file appropriately.
05. 
06.Parser Error Message: It is an error to use a section registered as
07.allowDefinition='MachineToApplication' beyond application level. 
08.This error can be caused by a virtual directory not being configured
09.as an application in IIS.
10. 
11.Source Error:
12. 
13. 
14.Line 53:
15.Line 54: 
16.Line 55:
17.Line 56:

Solution

Change authentication mode to 'None' in web.config.

Go to your web.config file and change following line

1. 
to
1.< authentication mode="None" />

This should solve this problem.

Note: If above solution does not work then make sure that the directory from where you website is running is configured as an application in IIS. To do this, you need to go into IIS and find your project folder on the server, right click to Properties. Under Application Settings click Create.

Cause

By default ASP.Net creates Windows authentication mode in Web.Config file. When you run this site locally on your computer, it runs fine. This is because it runs under current windows account credentials (i.e. Your windows login which may have administrative rights). But when you copy it to web server it runs under [MACHINENAME]\ASPNet account. If it does not have appropriate rights, server will throw this error.

The relative virtual path MyUserControl.ascx is not allowed here error in Web.Config

The relative virtual path MyUserControl.ascx is not allowed here error in Web.Config

Problem

I am trying to add a user control in Web.Config file as below,
 
< controls> 
< add tagPrefix="MyControl" tagName="MyUserControl" src="/MyUserControl.ascx"/> 
< /controls> 
It gives me following error,

Configuration Error: The relative virtual path 'MyUserControl.ascx' is not allowed here.

Solution

To resolve this issue, move your WebUserControl from root directory to a sub directory. For example in my case, I would copy MyUserControl.ascx to sub folder "Controls". So my Web.Config entry should look like below.
 
< controls> 
< add tagPrefix="MyControl" tagName="MyUserControl" src= "~/Controls/MyUserControl.ascx"/> 
< /controls> 
~ indicates relative path from root folder.
This is one of the limitation of ASP.Net application. It does not allow you to register user control in Web.Config file unless it's in a subfolder.

Send Email from your GMAIL account using ASP.Net and C#

Send Email from your GMAIL account using ASP.Net and C#

Send email using Gmail account

Download Sample

You can use your gmail account to send emails from ASP.Net and C#, using SMTP. You need to set SSL credentials. This is not straight forward like a simple SMTP email. After searching for long hours I was able to find a solution. Use following class to send emails using your GMAIL account.

Please supply your gmail user name and password in following class where needed.

01.using System.Web.Mail;
02.using System;
03.public class MailSender
04.{
05.public static bool SendEmail(
06.string pGmailEmail,
07.string pGmailPassword,
08.string pTo,
09.string pSubject,
10.string pBody,
11.System.Web.Mail.MailFormat pFormat,
12.string pAttachmentPath)
13.{
14.try
15.{
16.System.Web.Mail.MailMessage myMail = new System.Web.Mail.MailMessage();
17.myMail.Fields.Add
19."smtp.gmail.com");
20.myMail.Fields.Add
22."465");
23.myMail.Fields.Add
25."2");
26.//sendusing: cdoSendUsingPort, value 2, for sending the message using
27.//the network.
28. 
29.//smtpauthenticate: Specifies the mechanism used when authenticating
30.//to an SMTP
31.//service over the network. Possible values are:
32.//- cdoAnonymous, value 0. Do not authenticate.
33.//- cdoBasic, value 1. Use basic clear-text authentication.
34.//When using this option you have to provide the user name and password
35.//through the sendusername and sendpassword fields.
36.//- cdoNTLM, value 2. The current process security context is used to
37.// authenticate with the service.
38.myMail.Fields.Add
40.//Use 0 for anonymous
41.myMail.Fields.Add
43.pGmailEmail);
44.myMail.Fields.Add
46.pGmailPassword);
47.myMail.Fields.Add
49."true");
50.myMail.From = pGmailEmail;
51.myMail.To = pTo;
52.myMail.Subject = pSubject;
53.myMail.BodyFormat = pFormat;
54.myMail.Body = pBody;
55.if (pAttachmentPath.Trim() != "")
56.{
57.MailAttachment MyAttachment =
58.new MailAttachment(pAttachmentPath);
59.myMail.Attachments.Add(MyAttachment);
60.myMail.Priority = System.Web.Mail.MailPriority.High;
61.}
62. 
63.System.Web.Mail.SmtpMail.SmtpServer = "smtp.gmail.com:465";
64.System.Web.Mail.SmtpMail.Send(myMail);
65.return true;
66.}
67.catch (Exception ex)
68.{
69.throw;
70.}
71.}
72.}


Example usage of this class,
1.EmailLib.SendEmail.SendEmail("your_gmail_id",
2."your_gmail_password",
3."to_email @ anydomain.com",
4."This is email subject" ,
5."This is email body",
6.Web.Mail.MailFormat.Text,
7."Physical path to your Attachment")

Note: If you do not want to attach a file with email, supply blank string as "".

Implementing Amazon API Signed Requests Helper in ASP.Net and C#

Implementing Amazon API Signed Requests Helper in ASP.Net and C#


'Amazon

'Download Download Sample

Introduction

As many of you know, Starting August 15, 2009, all Amazon API requests must be authenticated using signatures.There is a whole bunch of documentation on Amazon website that describes how to authenticate requests. Visit following URL for more information.
http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html?RequestAuthenticationArticle.html
But as a newbie to Amazon APIs it was lot more difficult for me to build a working sample in ASP.Net and C#. After hours of search, I came across following article that helped me build my first successful sample. This article provided me a helper class in VB that can be used to generate a signed URL. I had to convert it in C#.
http://solutions.amazonwebservices.com/connect/thread.jspa?threadID=33790

Description

Download my sample code from above link and open it with Visual Studio 2005 or 2008 as a website. I have used .Net Framework 2.0 for this sample. But it should work fine with version 3.5 as well.
Most of the sample code is self explanatory. Comments are written inline with source code which should help you get started.
Following are key notes for this sample to work.
Go to Default.aspx.cs file and change your access key and secret key in following lines
1.private const string MY_AWS_ACCESS_KEY_ID = '<Enter />';
2.private const string MY_AWS_SECRET_KEY = '<Enter />';
If you are behind corporate firewall or proxy, you may need to authenticate HTTP requests. For that go to Web.config file and enter your windows user name and password in app.Settings.
1.<appSettings>
2.<add key="WindowsUserName" value="''/" />
3.<add key="WindowsPassword" value="" />
4.</appSettings>

Source Code Explanation

Most important part in this sample are following lines which are used to generate signed URL.
01.//Use SignedRequesthelper class to generate signed request.
02. 
03.SignedRequestHelper helper = new SignedRequestHelper(MY_AWS_ACCESS_KEY_ID, MY_AWS_SECRET_KEY, DESTINATION);
04. 
05.IDictionary requestParams = new Dictionary();
06. 
07.requestParams['Service'] = 'AWSECommerceService';
08. 
09.//Leave following line commented if you want to use latest version of Amazon API. You can uncomment this line to use a specific version.
10.//requestParams['Version'] = '2009-03-31';
11. 
12.requestParams['Operation'] = 'ItemSearch';
13.requestParams['SearchIndex'] = selectCategories.Value;
14.requestParams['Keywords'] = txtSearch.Text;
15. 
16.//Get signed URL in a variable
17.string requestUrl = helper.Sign(requestParams);
As you can see requestParams is an array which holds all the parameters to be passed along with request url.
Once you have signed URL ready, you can use WebRequest class to get response from Amazon web service.
01.DataSet GetData(string signedurl)
02.{
03.try
04.{
05.//Create a request object using signed URL.
06.WebRequest request = HttpWebRequest.Create(signedurl);
07.//Get response in a stream
08.Stream responseStream = request.GetResponse().GetResponseStream();
09. 
10.DataSet DS = new DataSet();
11.//Read returned resonpse stream into a dataset.
12.//Note: You can also use XMLDocument element here to read response.
13.DS.ReadXml(responseStream);
14.responseStream.Close();
15. 
16.return DS;
17.}
As you can see in above code, we get response in XML format which is then read into a Dataset. Dataset stores it as Tables.
Note that I am not referencing Amazon Web Service in this project. It could have been lot more easier to just use web methods to get Items. But unfotunately I could not find any way of signing a request with webservice.
Once we have returned data into dataset we can just bind these tables with Grid View or whatever way you want to use it.

Final Notes

In my sample I have just implemented search service from amazon. You can also implement Item Lookup in similar way. You just need to change request parameters in my sample. Feel free to modify it as you desire.

Google Maps Control for ASP.Net - Part 2

Google Maps Control for ASP.Net - Part 2

Free Open source Control

Google Map Control for ASP.Net

Introduction

This is second part in two part series of my article Google Maps User Control for ASP.Net. In first part Google Maps Control for ASP.Net - Part 1 I have explained how to use this control in your ASP.Net application. In this part I am going to explain source code of this user control so that you can modify it for your own use.

Diagram

Google Map Control Logical Diagram
Diagram above shows working flow of this user control. I will explain you one by one each element in this diagram.

ASPX page with Google Map User Control

  • As I mentioned in part 1, we need to initialize few properties of this user control to make it work. These properties are initialized in Page_Load() event of ASPX page.
    01.protected void Page_Load(object sender, EventArgs e)
    02.{
    03.//Specify API key
    04.GoogleMapForASPNet1.GoogleMapObject.APIKey =
    05.ConfigurationManager.AppSettings["GoogleAPIKey"];
    06. 
    07.//Specify width and height for map.
    08.GoogleMapForASPNet1.GoogleMapObject.Width = "800px";
    09.// You can also specify percentage(e.g. 80%) here
    10.GoogleMapForASPNet1.GoogleMapObject.Height = "600px";
    11. 
    12.//Specify initial Zoom level.
    13.GoogleMapForASPNet1.GoogleMapObject.ZoomLevel = 14;
    14. 
    15.//Specify Center Point for map.
    16.GoogleMapForASPNet1.GoogleMapObject.CenterPoint =
    17.new GooglePoint("1", 43.66619, -79.44268);
    18. 
    19.//Add pushpins for map.
    20.//This should be done with intialization of GooglePoint class.
    21.//In constructor of GooglePoint, First argument is ID of this pushpin.
    22.//It must be unique for each pin. Type is string.
    23.//Second and third arguments are latitude and longitude.
    24.GoogleMapForASPNet1.GoogleMapObject.Points.Add(
    25.new GooglePoint("1", 43.65669, -79.45278));
    26.}
  • When you initialize these properties, they gets stored in GOOGLE_MAP_OBJECT session variable. Later on this session variable is accessed by GService.asmx web service to draw google map.
  • Go to source of GoogleMapForASPNet.aspx.cs file. Check Page_Load() method.
    01.protected void Page_Load(object sender, EventArgs e)
    02.{
    03..
    04..
    05..
    06.if (!IsPostBack)
    07.{
    08.Session["GOOGLE_MAP_OBJECT"] = GoogleMapObject;
    09.}
    10.else
    11.{
    12.GoogleMapObject = (GoogleObject)Session["GOOGLE_MAP_OBJECT"];
    13..
    14..
    15..

    As you can see, I am storing GoogleMapObject property in a session variable if this is a first time load of page. If this is a post back then I use existing session variable value and assign it to GoogleMapObject property.

User Control (GoogleMapForASPNet.ascx)

  • GoogleMapForASPNet.ascx file contains a &ltDIV> element with ID=GoogleMap_Div. Google map is drawn on this &ltDIV> element
  • GoogleMapForASPNet.ascx is responsible for calling DrawGoogleMap() javascript function on page load. If you see source of GoogleMapForASPNet.ascx.cs file, it contains following lines in Page_Load() event.
    1.Page.ClientScript.RegisterStartupScript(Page.GetType(), "onLoadCall", "
    2.if (window.DrawGoogleMap) { DrawGoogleMap(); }
    3.");

    This causes DrawGoogleMap() function to get fired.

GoogleMapAPIWrapper.js

  • This javascript acts as a wrapper between ASP.Net calls and Google Maps Core API functions.
  • When DrawGoogleMap() function is called, it calls web service method GService.GetGoogleObject() to get session variable values.
  • Once different parameters are retrieved from session variable, it will start calling Google Maps core API functions to draw a map.

Web Service (GService.asmx)

  • As I have mentioned before, GService.GetGoogleObject() and GService.GetGoogleObjectOptimized() are functions defined in GService.asmx file.
  • These functions retrieves Google Map parameters from session variable.

How to define a Web Service Method

  • This control uses Web Service Methods to get values from a session variable. These methods are defined in Gservice.cs(GService.asmx code behind) file.
  • Go to source of GService.cs file. Observe how GetGoogleObject() web method is defined.
    01.[WebMethod(EnableSession = true)]
    02.public GoogleObject GetGoogleObject()
    03.{
    04.GoogleObject objGoogle = 
    05.(GoogleObject)System.Web.HttpContext.Current.Session["GOOGLE_MAP_OBJECT"];
    06. 
    07.System.Web.HttpContext.Current.Session["GOOGLE_MAP_OBJECT_OLD"] =
    08.new GoogleObject(objGoogle);
    09.return objGoogle;
    10.}

    Return value type from this method is GoogleObject.

How to call ASP.Net function (Web service method) from Javascript using a Web Service

  • If you go to HTML source of GoogleMapForASPNet.ascx file, you will see that I am using <ScriptManagerProxy> control.
    1. 
    When &ltServiceReference> is used with &ltScriptManagerProxy> or &ltScriptManager> controls, it allows you to use web service methods defined in code behind.
  • Go to source of GoogleMapAPIWrapper.js file. Observe how I am calling a web service method in DrawGoogleMap() function.
    01.function DrawGoogleMap()
    02.{
    03.if (GBrowserIsCompatible())
    04.{
    05.map = new GMap2(document.getElementById("GoogleMap_Div"));
    06.geocoder = new GClientGeocoder();
    07. 
    08.GService.GetGoogleObject(fGetGoogleObject);
    09.}
    10.}

    GService.GetGoogleObject() is a web service method. fGetGoogleObject() is a javascript function that should be called once web service method returns.
    01.function fGetGoogleObject(result, userContext)
    02.{
    03.map.setCenter(new GLatLng(result.CenterPoint.Latitude,
    04.result.CenterPoint.Longitude), result.ZoomLevel);
    05. 
    06.if(result.ShowMapTypesControl)
    07.{
    08.map.addControl(new GMapTypeControl());
    09.}
    10..
    11..
    12..

    result
    is return value from web service method GService.GetGoogleObject(). Thus result is of type GoogleObject. You can access properties of result in javascript to get map parameters.

Difference between GetGoogleObject() and GetGoogleObjectOptimized()

  • Both of these methods work in similar fashion. GetGoogleObject() is called when page loads for first time. It returns all of the GoogleObject properties to javascript function. While GetGoogleObjectOptimized is called on postback. It does not return all of the properties. Instead it returns minimum properties required to make a change in existing map.
  • If you view source of GoogleMapAPIWrapper.js file, there are two functions defined in it as below,
    01.function endRequestHandler(sender, args)
    02.{
    03.GService.GetOptimizedGoogleObject(fGetGoogleObjectOptimized);
    04.}
    05.function pageLoad()
    06.{
    07.if(!Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack())
    08.Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequestHandler);
    09.

    These function causes GService.GetOptimizedGoogleObject() to get fired when an AJAX call finishes. For example let's say you have a button in an UpdatePanel. When you click it, it postbacks the page. When this postback completes, above function will get fire.

Functions defined in GoogleMapAPIWrapper.js

  • To make this article short, I don't want to explain each and every function defined in this file. Instead I will explain important functions only. If you want more details for any code that's not explained here, you can post your questions in Comments section..
  • 01.function CreateMarker(point,icon1,InfoHTML,bDraggable,sTitle)
    02.{
    03.var marker;
    04.marker = new GMarker(point,{icon:icon1,draggable:bDraggable,title: sTitle});
    05.if(InfoHTML!='')
    06.{
    07.GEvent.addListener(marker, "click", function() { this.openInfoWindowHtml(InfoHTML); });
    08.}
    09.GEvent.addListener(marker, "dragend", function() { 
    10.GService.SetLatLon(this.value,this.getLatLng().y,this.getLatLng().x);
    11.RaiseEvent('PushpinMoved',this.value);  });
    12.return marker;
    13.}

    This function creates a marker on Google Map. As you can see, I am adding two events with each marker. First one is click(). When a user clicks on marker, a balloon (info window) pops up. This is a javascript event. Second one is dragend(). If a user wants he can drag a pushpin to a new location. This will cause a web method GService.SetLatLon() to get executed. This method sets new latitude and longitude values in Session Variable. As you can see this function also calls RaiseEvent() function which causes an AJAX postback.
    1.function RaiseEvent(pEventName,pEventValue)
    2.{
    3.document.getElementById('').value = pEventName;
    4.document.getElementById('').value = pEventValue;
    5.__doPostBack('UpdatePanel1','');
    6.}

    When postback finishes, new latitude and longitude values will be picked up from Session Variable.
  • 1.function RecenterAndZoom(bRecenter,result)

    This function causes Recentering of map. It finds all visible markers on map and decides center point and zoom level based on these markers.
  • 1.function CreatePolyline(points,color,width,isgeodesic)

    This function creates polylines between given points. See Polylines property in GoogleObject class.
  • 1.function CreatePolygon(points,strokecolor,strokeweight,strokeopacity,fillcolor,fillopacity)

    This function creates polygons between given points. See Polygons property in GoogleObject class.

How to define Icons for google map

  • If you see implementation of fGetGoogleObject() and fGetGoogleObjectOptimized() javascript functions, you can see that I am creating custom icons for google map. This is how they are defined.
    01..
    02..
    03.myIcon_google = new GIcon(G_DEFAULT_ICON);
    04.markerOptions = { icon:myIcon_google };
    05. 
    06.myIcon_google.iconSize = new GSize(result.Points[i].IconImageWidth,
    07.result.Points[i].IconImageHeight);
    08.myIcon_google.image = result.Points[i].IconImage;
    09.myIcon_google.shadow = result.Points[i].IconShadowImage;
    10.myIcon_google.shadowSize = new GSize(result.Points[i].IconShadowWidth,
    11.result.Points[i].IconShadowHeight);
    12.myIcon_google.iconAnchor =  new GPoint(result.Points[i].IconAnchor_posX,
    13.result.Points[i].IconAnchor_posY);
    14.myIcon_google.infoWindowAnchor = new GPoint(result.Points[i].InfoWindowAnchor_posX,
    15.result.Points[i].InfoWindowAnchor_posY);
    16..
    17..
  • There are various properties that you can set for a custom icon. Following article explains you each of these properties in detail.
    Making your own custom markers