Arturito.net

Come to The Dark Side, We Have Cookies!

Archive for the ‘C sharp’ Category

ASP.MVC 2 – How to migrate project from ASP.NET 2.0 .NET Framework 3.5 to ASP.NET 4.0 .NET Framework 4

without comments

So you have decided to move your ASP.NET MVC2 project  from the Windows Server configured with  ASP.NET 2.0 .NET Framework 3.5
to  ASP.NET 4.0 .NET Framework 4.

Here is how I did it.

My old setup:

Windows Server 2008 R2
IIS 7.5
ASP.NET
Application Pool : .NET Framework v2.0.50727
.NET Framework installed:  3.5 SP1

My new setup:

Windows Server 2008 R2
IIS 7.5
ASP.NET
Application Pool : .NET Framework v4.0.30319
.NET Framework installed:  4.0

The good thing is that the ASP.NET is backward compatible. You shoud publish the website on the new setup and it should work straight away.

In my case I had to remove these from web.config:


<section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirepermission="false" allowdefinition="MachineToApplication"></section>
<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirepermission="false" allowdefinition="Everywhere"></section><section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirepermission="false" allowdefinition="MachineToApplication"></section><section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirepermission="false" allowdefinition="MachineToApplication"></section><section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirepermission="false" allowdefinition="MachineToApplication"></section>

If it still gives you problems got to IIS Manager and click Error Pages:

Select 500 , right click and select Edit Feature Settings

Here select “Detailed errors”

Now you should get detailed error within your web.config. Also check Event Viewer under the section Administrative Events

Written by arturito

January 25th, 2012 at 10:20 am

ASP.NET MVC2 Visual Studio Error – The project type is not supported by this installation

without comments




If you get this error when opening a solution in Visual Studio, just go to the project file (YourProject.csproj) which fails to open and change the line

<ProjectTypeGuids>{Some_GUID}</ProjectTypeGuids>

to

<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>



Written by arturito

November 16th, 2011 at 8:03 am

ASP.NET MVC2 in the web farm – slow page load with high traffic – where is the bottleneck?

with one comment

Recently I have implemented quite complex e-commerce web application using technologies such as: ASP.NET MVC2, Linq2SQL , .NET 3.5 , SQL Server 2008 R2.

We have the whole thing hosted in the web farm.

We have 4 x IIS7 + 1 SQL SERVER 2008 load balanced with MS NLB

Static content is cached by external cache provider – Akamai, which reduces 86% of the requests.

Each web server has 32 GB of RAM and 4 x quad core CPUs so there are 64 cores on the front-end.

We store session state in tables of SQL server.

It works prefectly with medium traffic (page load = 0.2 -0.3 s)

but the company does the tv ads and during those ads the traffic hits up to 20,000 -30,000 users within 20-30 seconds.

In this moment the page slows down to 39 seconds. However, the usage of CPU’s and the memory doesn’t even arrive to 40% on any machine.

The bandwidth of the data centre does not arrive to the half of its limits.

Pages which are slow generate data from simple SELECTs of maximum 10 records from 1-2 tables only.

I gone through all possible things: I already had my queries compiled but I also optimized selects, created additional indexes studied a lot the problems of storing session in tables that sql server 2005 had (temdb) and I couldn’t figure out what was going on.

You could reproduce the the problem by launching stress tools against the web. The worst thing was that we could freeze the web just by launching stress tools from only two pc’s located in our offices.

I have also posted the question on stackoverflow
http://stackoverflow.com/questions/7644339/asp-net-mvc2-in-the-web-farm-slow-page-load-with-high-traffic
where people suggested to check indexes and use CompiledQuery.

In practice 90% of the bottlenecks are caused by database. After the whole week of tests and studying the problem I have possibly found a bug in the ASP.NET MVC2 library.
It was incredible how silly the thing was:

Let’s have a look at this code:


public ActionResult Index(){
var model = new SomeModel();
// Get data
....
return View(model);
}

In this code the View is generated using file Index.aspx.
However, this View needs to be found in some way and I guess the search of the this View is causing the problem.

Unbelievable but true – adding the name of the View removed the problem:


public ActionResult Index() {
 var model = new SomeModel();
// Get data
....
return View("Index",model);
}

I say it again, this problem does exists only when the web has a high number of users.
The MVC version I’m using is

Version: 2.0.0.0
Runtime: v2.0.50727

I have contacted the geeks responsible for the design and development of this great library to see what they say.

By all means I don’t  want to discourage anyone to use this library as it is absolutely fantastic and I use it a lot and I will carry on using it.

 

 

 

Written by arturito

October 24th, 2011 at 10:59 am

How to remove Server, X-AspNet-Version, X-AspNetMvc-Version and X-Powered-By from the response header in IIS7

without comments

You can check your response headers by using Firebug add-on for Firefox or just hit Ctrl+J in Chrome.

Unwanted info:

Server Microsoft-IIS/7.5
X-AspNetMvc-Version 3.0
X-AspNet-Version 4.0.303319
X-Powered-By ASP.NET

 

1. Removing X-AspNet-Version

In web.config stick this line in


<system.web>
      <httpRuntime enableVersionHeader="false"/>
	...

2. Removing X-AspNetMvc-Version

In Global.asax.cs add this line:


protected void Application_Start()
{
    MvcHandler.DisableMvcResponseHeader = true;
}

3. Removing or changing Server

Add this module class to your project.


using System;
using System.Web;

namespace Project.Infrastructure.Web.Modules.Http
{
    public class CustomHeaderModule : IHttpModule
    {
        public void Init(HttpApplication context)
        {
            context.PreSendRequestHeaders += OnPreSendRequestHeaders;
        }

        public void Dispose() { }

        void OnPreSendRequestHeaders(object sender, EventArgs e)
        {
	     //HttpContext.Current.Response.Headers.Remove("Server");
            // Or you can set something funny
	    HttpContext.Current.Response.Headers.Set("Server", "CERN httpd");
        }
    }
}

And add set it in web config


	<system.webServer>
		<modules>
        <add name="CustomHeaderModule" type="StrongNamespace.HttpModules.CustomHeaderModule" />

4. Removing or changing X-Powered-By

Go to IIS7 Management Console and open HTTP Response Headers

And that should be it!

 

Written by arturito

October 21st, 2011 at 7:07 am

How to Switch Between HTTP and HTTPS in ASP.NET MVC2 And Allow AJAX Requests From Site Master.

without comments

In order to serve the request throught SSL in ASP.NET MVC2 we can simple use Action attribute [RequireHttps]:

		//LoginController
        [RequireHttps]
        public ActionResult Index()
        {
            return View();
        }

Let’s say I served a login form here. Then the user logs in.

		//LoginController
        [RequireHttps]
        [HttpPost]
        public ActionResult Index(LoginModel model)
        {
            if (model != null && model.Username == "arturito")
                 return RedirectToAction("List", "Home");
            else
                return RedirectToAction("Login");
        }

Note that the redirection ( RedirectToAction(“List”, “Home”) ) is taking us to HomeController List action.
However the action List in HomeController is not decorated in [RequireHttps] so it should return to HTTP.

        //HomeController
		public ActionResult List()
        {
            return View();
        }

BUT IT DOESN’T!
You will remain in HTTPS.

Jeff Widmer worked out a great solution and posted it in his article.
In his solution we have BaseController and we are overriding OnAuthorization method

    public class BaseController : Controller
    {
            protected override void OnAuthorization(AuthorizationContext filterContext)
            {

                //the RequireHttpsAttribute set on the Controller Action will handle redirecting to Https.
                // We just need to handle any requests that are already under SSL but should not be.
                if (Request.IsSecureConnection)
                {
                    Boolean requireHttps = false;
                    requireHttps = filterContext.ActionDescriptor.GetCustomAttributes(typeof(RequireHttpsAttribute), false).Count() >= 1;

                    //If this request is under ssl but yet the controller action
                    // does not require it, then redirect to the http version.
                    if (!requireHttps && !filterContext.IsChildAction)
                    {
                        UriBuilder uriBuilder = new UriBuilder(Request.Url);

                        //change the scheme
                        uriBuilder.Scheme = "http";
                        uriBuilder.Port = 80;

                        filterContext.Result = this.Redirect(uriBuilder.Uri.AbsoluteUri);
                    }
                }

                base.OnAuthorization(filterContext);
            }

    }

But there is one problem left!

Let’s say that all pages served through HTTP and HTTPS use the same site master page which contains a link or the form that creates ajax request.
As an example let’s look at this simple action:

		// Home Controller
        [HttpPost]
        public ActionResult Ajax()
        {
            return Content("This is Ajax");
        }

This works great from HTTP page!

How to Switch Between HTTP and HTTPS in ASP.NET MVC2 And Allow AJAX Requests From Site Master.

How to Switch Between HTTP and HTTPS in ASP.NET MVC2 And Allow AJAX Requests From Site Master.

….but when we call the same action from HTTPS page it doesn’t work!
How to Switch Between HTTP and HTTPS in ASP.NET MVC2 And Allow AJAX Requests From Site Master.

Why? This is called crossdomain ajax request, which by default is not allowed for security reasons. There are some methods/libraries/proxies to achieve this but it is not very common yet.

If we decorate it with [RequireHttps] attribute:

		// Home Controller
		[RequireHttps]
        [HttpPost]
        public ActionResult Ajax()
        {
            return Content("This is Ajax");
        }

This action becomes available only if requested from the page served through HTTPS. We can no longer call it from the page served through http.

Well then, let’s allow to perform all ajax request from pages served by both HTTP and HTTPS:

protected override void OnAuthorization(AuthorizationContext filterContext)
            {

                //the RequireHttpsAttribute set on the Controller Action will handle redirecting to Https.
                // We just need to handle any requests that are already under SSL but should not be.
                if (Request.IsSecureConnection)
                {
                    Boolean requireHttps = false;
                    requireHttps = filterContext.ActionDescriptor.GetCustomAttributes(typeof(RequireHttpsAttribute), false).Count() >= 1;

                    // Allow Ajax request from both http and https pages
                    if (Request.IsAjaxRequest())
                    {
                        base.OnAuthorization(filterContext);
                        return;
                    }

                    //If this request is under ssl but yet the controller action
                    // does not require it, then redirect to the http version.
                    if (!requireHttps && !filterContext.IsChildAction)
                    {
                        UriBuilder uriBuilder = new UriBuilder(Request.Url);

                        //change the scheme
                        uriBuilder.Scheme = "http";
                        uriBuilder.Port = 80;

                        filterContext.Result = this.Redirect(uriBuilder.Uri.AbsoluteUri);
                    }
                }

                base.OnAuthorization(filterContext);
            }

    }

Now whether we are on login page (HTTPS) or any other page (HTTP) we can create ajax requests in the site master without decorating ajax actions with additional attributes or messing around
with url scheme in the Views.

Here is a downloadable example:  http://www.mediafire.com/?0d6dn6w489yalgo

GL

Written by arturito

August 5th, 2011 at 4:12 pm

ASP.NET MVC 2 Highlight Selected Menu Item on the Site Master Without Session

with 5 comments

ASP.NET MVC2 makes so many things so easy to program but there are some basic things that are just not there and they should be.
I will be talking about a basic functionality that is a must these days.
I am talking about a menu and highlighting selected menu item.

Let’s see the problem:

I have 3 links and with each click I would like to add apropiate css class to mark my menu item as selected.

ASP.NET MVC 2 Highlight Selected Menu Item on the Site Master Without Session

I have follwed an article on bobby’s blog.
So with this great extension it does work really well:

  public static class HtmlExtensions
    {
        public static MvcHtmlString ActionMenuItem(this HtmlHelper htmlHelper,
        String linkText, String actionName, String controllerName)
        {
            var tag = new TagBuilder("li");
            if (htmlHelper.ViewContext.RequestContext.IsCurrentRoute(
            null, controllerName, actionName) ||
            htmlHelper.ViewContext.RequestContext.IsParentRoute(
            controllerName, actionName))
            {
                tag.AddCssClass("active");
            }
            tag.InnerHtml = htmlHelper.ActionLink(linkText, actionName, controllerName).ToString();

            return MvcHtmlString.Create(tag.ToString());
        }
    }

In the place of menu we stick this:

<%= Html.ActionMenuItem("Home", "Index", "Home") %>

However, there was a one little thing missing in it that I needed to have on my web.

ASP.NET MVC 2 Highlight Selected Menu Item on the Site Master Without Session

In the About link I have a link to Biography . (Biography controller and Index action)
Since the Biography page is a part of About section I would like the “About” menu item to remain highlighted.
The solution above doesn’t work in that case.
So I decided to modify it a bit.

Let’s start from the extension:

    public static class HtmlExtensions
    {
        public static MvcHtmlString ActionMenuItem(this HtmlHelper htmlHelper, String linkText, String actionName, String controllerName)
        {
            var tag = new TagBuilder("li");

            if (htmlHelper.ViewContext.RequestContext.IsCurrentRoute(null, controllerName, actionName) ||
                htmlHelper.ViewContext.RequestContext.IsParentRoute(controllerName, actionName))
            {
                tag.AddCssClass("active"); // stick class active
            }
            else
            {
                tag.AddCssClass("inactive"); // stick class inactive
            }

            tag.InnerHtml = htmlHelper.ActionLink(linkText, actionName, controllerName).ToString();

            return MvcHtmlString.Create(tag.ToString());
        }
    }
 

We also neeed Request Extensions:

    public static class RequestExtensions
    {
        public static bool IsCurrentRoute(this RequestContext context, String areaName)
        {
            return context.IsCurrentRoute(areaName, null, null);
        }

        public static bool IsCurrentRoute(this RequestContext context, String areaName, String controllerName)
        {
            return context.IsCurrentRoute(areaName, controllerName, null);
        }

        public static bool IsCurrentRoute(this RequestContext context, String areaName, String controllerName, params String[] actionNames)
        {
            var routeData = context.RouteData;
            var routeArea = routeData.DataTokens["area"] as String;
            var current = false;

            if (((String.IsNullOrEmpty(routeArea) && String.IsNullOrEmpty(areaName)) || (routeArea == areaName)) &&
                 ((String.IsNullOrEmpty(controllerName)) || (routeData.GetRequiredString("controller") == controllerName)) &&
                 ((actionNames == null) || actionNames.Contains(routeData.GetRequiredString("action"))))
            {
                current = true;
            }

            return current;
        }

        public static bool IsParentRoute(this RequestContext context, String controller, String action)
        {
            var routeData = context.RouteData;
            UrlModel returnUrl = null;
            UrlModel requestUrl = new UrlModel { Action = routeData.GetRequiredString("action"), Controller = routeData.GetRequiredString("controller") };
            UrlModel linkUrl = new UrlModel { Action = action, Controller = controller };

            var urls = UrlMap.GetDictionary();
            urls.TryGetValue(requestUrl, out returnUrl);

            if (returnUrl != null && returnUrl.Equals(linkUrl))
                return true;
            else
                return false; ;
        }
    }
 

And now the important part the UrlMap


    public static class UrlMap
    {
        public static Dictionary GetDictionary()
        {
            Dictionary urls = new Dictionary();
            urls.Add(new UrlModel { Controller = "Biography", Action = "Index" }, new UrlModel { Controller = "About", Action = "Index" });
            urls.Add(new UrlModel { Controller = "Contact", Action = "GetInTouch" }, new UrlModel { Controller = "Contact", Action = "Index" });
            return urls;
        }
    }

Here I specify that if Biography/Index is called please mark it the same as About/Index.

Don’t forget to create UrlModel class

public class UrlModel
    {
        public string Action { get; set; }
        public string Controller { get; set; }

        public override bool Equals(object obj)
        {
            return Equals(obj as UrlModel);
        }
        public bool Equals(UrlModel obj)
        {
            return obj != null && obj.Action == this.Action && obj.Controller == this.Controller;
        }
        public override int GetHashCode()
        {
            return (Action + Controller).GetHashCode();
        }
    }

Now you can stick HtmlHelper with menu in any place on the site.

    <ul id="menu">
        <%= Html.ActionMenuItem("Home", "Index", "Home") %>
        <%= Html.ActionMenuItem("About", "Index", "About") %>
        <%= Html.ActionMenuItem("Contact", "Index", "Contact") %>
    </ul>

and add as amny Url Mapsas you like:

 public static Dictionary GetDictionary()
        {
            Dictionary urls = new Dictionary();
            urls.Add(new UrlModel { Controller = "Biography", Action = "Index" }, new UrlModel { Controller = "About", Action = "Index" });
            urls.Add(new UrlModel { Controller = "Contact", Action = "GetInTouch" }, new UrlModel { Controller = "Contact", Action = "Index" });
            return urls;
        }

Here is how it looks: ASP.NET MVC 2 Highlight Selected Menu Item on the Site Master Without Session


ASP.NET MVC 2 Highlight Selected Menu Item on the Site Master Without Session


ASP.NET MVC 2 Highlight Selected Menu Item on the Site Master Without Session

Here is a complete solution to download: http://www.mediafire.com/?0xabi855suro2rl

GL!

Written by arturito

August 3rd, 2011 at 6:03 pm

ASP.NET MVC2 jQuery Form Post with JSON Tutorial

with 3 comments

In one of the previous post I covered how to post form with ASP.NET MVC2 using jQuery.

Today I will explain how to return data in JSON format. Why return data in JSON format. Well there are several reasons for it:

1. You can easily update several parts of the page without reloading entire page

Imagine that you have ajax login and after successful login the name of the user is updated in the header of the page and content of the saved cart in the right column.

2. It reduces the amount of data sent from the server to the browser.

In a lot of cases developers send data wrapped in html such as:


return Content(

You submitted: “ + data.FirstName + ” “ + data.LastName +

“);


or they send PartialView. But the idea of JSON is to send data only without html tags, which also reduces the traffic.

3. It separates application logic from design

Sending only data using JSON means data doesn’t have to be wrapped in html tags in your controller, you only send pure data. This way one developer can concentrate on developing logic and doesn’t have to think how it will be displayed, leaving web designer to handle presentation part.

Let’s start modifying previous project:

1. Open MVC2JQuery project that can be downloaded here MVC2JQuery at MediaFire

2. Open RegisterViewModel and modified it as below:


public class RegisterViewModel
{
public string FirstName { get set }
public string LastName { get set }
public int NumberOfPosts { get set }
public string LastPost { get set }
}


3. Open HomeController and make changes as shown below:


[HttpPost]
public ActionResult Index(RegisterViewModel data)
{

// here you can save data to database

// and return some feedback to the user

data.NumberOfPosts = 5;

data.LastPost = “This is my last post”

if(Request.IsAjaxRequest())

return Json(data);  // here data object is being converted to JSON format

else

return Content(“Please enable JavaScript”);

}


4. Also modify Views/Index accordingly

In the part:


<script type=”text/javascript” src=”<%=Url.Content("~/Scripts/jquery-1.4.4.min.js")%>“>script>
<script type=”text/javascript” src=”<%=Url.Content("~/Scripts/jquery.form.js")%>“>script>
<script type=”text/javascript”>

$(document).ready(function() {
var options = {
beforeSubmit: showRequest, // call this function before sending data to the server
success: showResponse, // call this function once we have a response form the server
type: ‘post’,
dataType: ‘json’, // important! expecting data type is JSON
resetForm: true
};

$(‘#form-user’).ajaxForm(options);
});

function showRequest(formData, jqForm, options) {
$(“#result-user”).empty().html(‘Loading….’); // display loading
$(“#form-user :input”).attr(“disabled”, true); // disable inputs
}

function showResponse(data, statusText, xhr, $form) {
$(“#result-user”).empty();
$(“#form-user :input”).attr(“disabled”, false);
// here ‘data’ is an object. See below how it is used:
$(“#welcome”).html(“Hello, “ + data.FirstName + ” “ + data.LastName);
$(“#number”).html(“Number of posts: “ + data.NumberOfPosts);
$(“#lastpost”).html(data.LastPost);
}
script>


In the part:


<body>
<% using (Html.BeginForm(“Index”,“Home”,FormMethod.Post, new { id=“form-user”, name=“form-user”})) {%>

<div style=”float:left” id=”welcome”>div>
<div style=”float:right” id=”number”>div>
<div style=”clear:both“>div>
<fieldset>
<legend>Fieldslegend>

<
div class=”editor-label”>
<%=
Html.LabelFor(model => model.FirstName) %>
div
>

<
div class=”editor-field”>
<%=
Html.TextBoxFor(model => model.FirstName) %>
<%= Html.ValidationMessageFor(model => model.FirstName) %>
div
>

<
div class=”editor-label”>
<%=
Html.LabelFor(model => model.LastName) %>
div
>

<div class=”editor-field”>
<%=
Html.TextBoxFor(model => model.LastName) %>
<%= Html.ValidationMessageFor(model => model.LastName) %>
div>

<p>
<input type=”submit” value=”Save” />
p>

fieldset>

<% } %>

<div id=”result-user”>div>
<div style=”border:solid 1px #cccmargin:10px id=”lastpost” >div>
body>


5. And we are done! Hit F5 and see result:

ASP.NET MVC2 JQuery JSON Form Post

Here you can download complete source code: http://www.mediafire.com/?ul8wl6o2fe47qk4

Good Luck!

Written by guru

January 25th, 2011 at 9:11 pm

Posted in ASP.NET MVC2,C sharp

Publishing ASP.NET MVC2 Application on Windows Server 2008 IIS 7 with Visual Studio 2008 on platform .NET 3.5 SP1

without comments

Prepare you server:

1. Go to Server Manager and select Add Roles, and install Web Server

2. Mark ASP.NET and install

3. Confirm the CLR of ASP.NET has been installed

4. Install .NET Framework 3.5 and .NET Framework 3.5 SP1

5. Let’s create a directory where we stick our MVC2 application. In my case it is C:\www\windows.amk

6. Once you are done go to the Security properties of that directory and add read and write permissions for group IIS_IUSRS

7. Go back to IIS Manager and Add Site

8. In Application Pool double click pool of your site and make sure that Managed pipeline mode is Integrated

Now the server is prepared to run MVC2 web application!

Prepare your project to be published

1. Go to your project properties and mark Release

2. Go to References and and change Property Copy Local to true for

System.ComponentModel.DataAnnotations.dll
System.Web.Mvc.dll

If you are running .NET Framework 3.5 NOT .NET Framework 3.5 SP1 change properties for all these.

System.ComponentModel.DataAnnotations.dll
System.Web.Abstractions.dll
System.Web.Mvc.dll
System.Web.Routing.dll

6. In Web.config change lines

<compilation debug="true">

to

<compilation debug="false">

And uncomment this bit:

        <customerrors mode="RemoteOnly" defaultredirect="GenericErrorPage.htm">
            <error statuscode="403" redirect="NoAccess.htm" />
            <error statuscode="404" redirect="FileNotFound.htm" />
        </customerrors>

 

7. Generate and upload files to directory on the server in my case c:\www\windows.amk

* What we need:
- Configuration and settings files (e.g., Web.config and any *.settings files)
- Uncompiled view templates (*.aspx, *.ascx, and *.Master)
- Global.asax (this tells ASP.NET which compiled class represents your global HttpApplication)
- Any static files (e.g., images, CSS files, and JavaScript files)
- Optionally, the *.pdb files in your \bin folder, which enable extra debugging information (these are rarely deployed to production servers)

* We don’t need:

- C# code files (*.cs, including Global.asax.cs or any other ‘code behind’ files)
- Project and solution files (*.sln, *.suo, *.csproj, or *.csproj.user)
- The \obj folder
- Anything specific to your source control system (e.g., .svn folders if you use Subversion, or the .hg or .git folders if you use Mercurial or Git)

Good Luck!

Written by guru

January 21st, 2011 at 8:45 am

Posted in ASP.NET MVC2,C sharp

Using Google Maps API to mark multiple addresses fetched from database ASP.NET MVC2 and Geocoder

without comments

This tutorial will cover marking multiple addresses stored in database on Google Maps.  For example this can be useful for marking chain of shops or restaurants or others.
The idea is to get something like this:

Before starting it we have to obtain a key for using their API.
You can do it here:
http://code.google.com/apis/maps/signup.html

Generate your key and save it

1. Create new Empty MVC2 project
2. Insert new .ashx file call it Maps.ashx.

I placed mine the folder Services which I created before.

3. Insert this code


[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Maps : IHttpHandler    {

public void ProcessRequest(HttpContext context)        {
context.Response.ContentType = "text/xml";
context.Response.ContentEncoding = System.Text.Encoding.UTF8;
       string sXml = createMarkers();
       context.Response.Cache.SetExpires(DateTime.Now.AddSeconds(600));
context.Response.Cache.SetCacheability(HttpCacheability.Public);
context.Response.Write(sXml);
}
public bool IsReusable {
        get { return true; }
}

private string createMarkers() {
// Create the xml document container
XmlDocument doc = new XmlDocument();//
    Create the XML Declaration, and append it to XML document
    XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", null, null);
    doc.AppendChild(dec);// Create the root element
    XmlElement root = doc.CreateElement("markers");
    doc.AppendChild(root);
 // Here you can create a loop and fetching data from database like
  /*  while(rdr.Read()) {
XmlElement marker = doc.CreateElement("marker");
marker.SetAttribute("name",  rdr["name"].ToString());
marker.SetAttribute("address", rdr["address"].ToString());
                   root.AppendChild(marker);
      }
*/

// To retrieve data using a C# go here:
// http://www.akadia.com/services/dotnet_data_reader.html
// We will enter it manually

 XmlElement marker = doc.CreateElement("marker");
marker.SetAttribute("name", "L'arruzz");
 marker.SetAttribute("address", "C/ PORTUGAL, 35, 03003 ALICANTE");
root.AppendChild(marker);

 XmlElement marker2 = doc.CreateElement("marker");
 marker2.SetAttribute("name", "CERVECERIA VICTOR");
marker2.SetAttribute("address", "C/ SAN AGATÁNGELO, 37, 03007 ALICANTE");
root.AppendChild(marker2);
return doc.OuterXml;
}
}

4. Next step is to create HomeController and create Index View.

public ActionResult Index()
{            return View();
}

5. Now run your project and check if xml is being genrated by go to url of ashx file:

http://localhost:your_port_number/Services/Maps.ashx

For example in my case:http://localhost:1951/Services/Maps.ashx

6. Go back your HomeController and right click and create Index View. Your code should be the same as below:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >

<head runat="server">
<title>Index</title>

<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=here_we_enter_google_api_key" type="text/javascript"></script>
 <script type="text/javascript">
 //<![CDATA[
 var map = null;
 var geocoder = null;
 function load() {
 if (GBrowserIsCompatible()) {
 map = new GMap2(document.getElementById("map"));
 map.addControl(new GSmallMapControl());

geocoder = new GClientGeocoder();

// Here enter your url of ashx file

GDownloadUrl("http://localhost:1951/Services/Maps.ashx", function(data) {
var xml = GXml.parse(data);
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++) {
 var name = markers[i].getAttribute("name");
 var address = markers[i].getAttribute("address");
 showAddress(address,name);
}
});

}
}

function showAddress(address, name) {
if (geocoder) {
geocoder.getLatLng(
name+","+address,
function(point) {
if (!point) {
 alert(address + " not found");
} else {
map.setCenter(point, 13);
var marker = createMarker(point, name, address);
map.addOverlay(marker);
}
});

}

}

function createMarker(point, name, address) {
var marker = new GMarker(point);
var html = "<b>" + name + "</b> <br/>" + address;
GEvent.addListener(marker, 'click', function() {
marker.openInfoWindowHtml(html);
});

return marker;
}

//]]>

</script>

</head>

<body onload="load()" onunload="GUnload()">
<div>
<div id="map" style="width: 1000px; height: 600px"></div>
</div>
</body>
</html>

Run it and there we go!

You can also do it without ashx and return xml as an ActionResult

public ActionResult PrintMarkers()  {
    XmlDocument doc = new XmlDocument();//
    Create the XML Declaration, and append it to XML document
    XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", null, null);
    doc.AppendChild(dec);// Create the root element
    XmlElement root = doc.CreateElement("markers");
    doc.AppendChild(root);

 XmlElement marker = doc.CreateElement("marker");
 marker.SetAttribute("name", "L'arruzz");
 marker.SetAttribute("address", "C/ PORTUGAL, 35, 03003 ALICANTE");
 root.AppendChild(marker);

 XmlElement marker2 = doc.CreateElement("marker");
 marker2.SetAttribute("name", "CERVECERIA VICTOR");
marker2.SetAttribute("address", "C/ SAN AGATÁNGELO, 37, 03007 ALICANTE");
root.AppendChild(marker2);
return doc.OuterXml;
}

And simply call it from script of JavaScript:

 GDownloadUrl("http://localhost:1951/Home/PrintMarkers/", function(data) {
var xml = GXml.parse(data);
var markers = xml.documentElement.getElementsByTagName("marker");
 for (var i = 0; i < markers.length; i++) {
var name = markers[i].getAttribute("name");
var address = markers[i].getAttribute("address");
showAddress(address,name);
}
});  

Will do the same.

Good luck! :)

Written by guru

December 13th, 2010 at 9:06 am

Posted in ASP.NET MVC2,C sharp

ASP.NET MVC2 jQuery Form Post Tutorial

with 8 comments

Here is a little tutorial that I wrote about posting form using jQuery and Form plugin.I’m using Visual Studio 2008.
If you want to see how to post form with JSON check my other post:
http://arturito.net/2011/01/25/asp-net-mvc2-jquery-form-post-with-json-tutorial/

1. Open Visual Studio

2. Create MVC2 Empty Web Application

3. Right click Controllers in Solution Explorer and select Add Controller

4. Name it HomeController

5. Right Click on Models in Solution Explorer and select Add Class…

6.  Name it RegisterViewModel

Insert this piece of code:

namespace MVC2JQuery.Models
{
    public class RegisterViewModel
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
}

7. In the Toolbar click Build->Build Solution

8. Go back to HomeController and right click on Index() and select Add View …

    public class HomeController : Controller
    {
        //
        // GET: /Home/

        public ActionResult Index() // <-- right click here
        {
            return View();
        }

    }


9. You will be taken to your Index.aspx

10. Now run the application by hitting F5 (Click ok on “Debugging Not Enabled” with option “Modify…”)

11. Now, let’s make it do something. Stop Debugging and go back to Home Controller and add Action:

        [HttpPost]
        public ActionResult Index(RegisterViewModel data)
        {
            // here you can save data to database
            // and return some feedback to the user
            return Content("You submitted: " +  data.FirstName + " " + data.LastName);
        }

12. Your HomeController will look like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MVC2JQuery.Models;

namespace MVC2JQuery.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/

        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Index(RegisterViewModel data)
        {
            // here you can save data to database
            // and return some feedback to the user
            return Content("You submitted: " +  data.FirstName + " " + data.LastName);
        }

    }
}

Build project and Run it.

13. Now go to Scripts in Solution Explorer and remove all file that are in there. We won’t be using them.

14. Download:

jQuery:
http://code.jquery.com/jquery-1.4.4.min.js

jQuery Form Plugin:
https://github.com/malsup/form/raw/master/jquery.form.js

Save them in Scripts folder of your project.


15. Go to Views and chaage Index.aspx as below:

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<mvc2JQuery.Models.RegisterViewModel>" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Index</title>
    <script type="text/javascript" src="<%=Url.Content("~/Scripts/jquery-1.4.4.min.js")%>"></script>
    <script type="text/javascript" src="<%=Url.Content("~/Scripts/jquery.form.js")%>"></script>
    <script type="text/javascript">
        $(document).ready(function() {
            var options = {
                target: '#result-user', // id of the div where we are going to display result
                beforeSubmit: showRequest,
                success: showResponse,
                type: 'post',
                resetForm: true
            };
            $('#form-user').ajaxForm(options); // id of the form we wish to submit
        });

        function showRequest(formData, jqForm, options) {
            $("#result-user").empty().html('Loading....');
            $("#form-user :input").attr("disabled", true); // disable all form inputs while loading
        }

        function showResponse(responseText, statusText, xhr, $form) {
            $("#result-user").empty().html(responseText);
            $("#form-user :input").attr("disabled", false);
        }
    </script>

</head>
<body>
    <% using (Html.BeginForm("Index","Home",FormMethod.Post, new { id="form-user", name="form-user"})) {%>

        <fieldset>
            <legend>Fields</legend>

            <div class="editor-label">
                <%= Html.LabelFor(model => model.FirstName) %>
            </div>
            <div class="editor-field">
                <%= Html.TextBoxFor(model => model.FirstName) %>
                <%= Html.ValidationMessageFor(model => model.FirstName) %>
            </div>

            <div class="editor-label">
                <%= Html.LabelFor(model => model.LastName) %>
            </div>
            <div class="editor-field">
                <%= Html.TextBoxFor(model => model.LastName) %>
                <%= Html.ValidationMessageFor(model => model.LastName) %>
            </div>

            <p>
                <input type="submit" value="Save" />
            </p>
        </fieldset>

    <% } %>
    <div id="result-user"></div>
</body>
</html>

16. Let’s go back to our HomeController and amend Index action:

        [HttpPost]
        public ActionResult Index(RegisterViewModel data)
        {
            // here you can save data to database
            // and return some feedback to the user

            if(Request.IsAjaxRequest())
                return Content("You submitted: " +  data.FirstName + " " + data.LastName + " using jQuery");
            else
                return Content("You submitted: " + data.FirstName + " " + data.LastName);
        }

17. Build and Run


Here you can download working example


Note:
If you are not getting the same result make sure that:
1.Ids are equal
$(‘#form-user‘).ajaxForm(options);
Html.BeginForm(“Index”,”Home”,FormMethod.Post, new { id=”form-user“, name=”form-user“})

$(“#result-user“).empty().html(responseText);

http://arturito.net/2011/01/25/asp-net-mvc2-jquery-form-post-with-json-tutorial/

Written by guru

December 2nd, 2010 at 8:11 pm

Posted in ASP.NET MVC2,C sharp