Click here to Skip to main content
15,312,745 members
Articles / Programming Languages / Razor
Posted 1 Aug 2013


91 bookmarked

Google Maps in MVC 4 with Custom InfoWindow

Rate me:
Please Sign up or sign in to vote.
4.82/5 (75 votes)
20 Aug 2013CPOL4 min read
A quick tutorial on using Google Maps in MS MVC 4


I was recently investigating using Google Maps in a web-application and couldn't find a clear example that showed how to do it with MVC 4. Hopefully, this article fills that gap! Technologies used include MS C# MVC 4, jQuery, and of course, the Google Maps API.


There were some "gotchas" I encountered while putting this together. The first is that (at least for me), using a jQuery selector to link my div that would contain the Google map didn't work. I had to specifically use the JavaScript document.getelementById call. The second was sizing. Using the default size (which was teeny weenie) wasn't cutting it for me, so I increased width/height. Turns out Google Map didn't like that too much. After a bit of digging, I found a post that said to create a quick in-page style that set the max-width to "none" ... then it worked.

Using the Code

Create a new MVC 4 project - this will include by default, appropriate links to jQuery and other supporting files you will need to run this tutorial.

All of the work we are doing is in the "Index view" - so go to that file and clean out any HTML, etc., you don't need.

Add in a script ref to the Google Maps API at the top of the file:

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

Somewhere near that (or in an external stylesheet if you wish), add in this tweak to ensure the map and its controls size correctly:

<style> #map_canvas img{max-width:none} </style>

Here is another piece of CSS I put in - it is to style the popup infoWindow (optional) when someone clicks on a map-marker.

    .infoDiv {
    height: 200px;    
    width: 300px; 
    -webkit-user-select: none; 
    background-color: white; 
}  </style>    

Before we drop in the script-code itself, we need to create a razor "SECTION" to surround the code. The reason for this is to let MVC manage the placement of the script within the output HTML file. This is important to ensure that things are loaded in the correct order.

If you look in the view folder, you will see a folder called "Shared" - in here is "_Layout.cshtml". This is the parent wrapper for the Index view page. At the bottom, you will notice these two lines:

@RenderSection("scripts", required: false)  

This tells the razor engine "render/load all the jQuery files, then once that is done, output any section marked as "scripts".

Let's go back to our view index page and add a section wrapper:

@section scripts { 
<section class="scripts">  
   <script type="text/javascript">
// our code will go in here...

Now the code that makes the magic happen:

<!-- This code tells the browser to execute the "Initialize" method 
         only when the complete document model has been loaded. -->
$(document).ready(function () {

Most will already know that the above is jQuery code that tells the browser only to execute the method Initialize once the entire document model has been loaded. This ensures JavaScript does not try to trigger or access an object that has not yet been created.

initialize is the main method that does all of the work

function Initialize() {

Google has tweaked their interface somewhat - this tells the API to use that new UI.

google.maps.visualRefresh = true;
var Liverpool = new google.maps.LatLng(53.408841, -2.981397);

These are options that set the initial zoom level, where the map is centered globally to start, and the type of map to show:

var mapOptions = {
    zoom: 14,
    center: Liverpool,
    mapTypeId: google.maps.MapTypeId.G_NORMAL_MAP

This makes the div with id map_canvas a Google map.

var map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);

This shows adding a simple pin "marker" - this happens to be the Tate Gallery in Liverpool!

var myLatlng = new google.maps.LatLng(53.40091, -2.994464);
var marker = new google.maps.Marker({
    position: myLatlng,
    map: map,
    title: 'Tate Gallery'

You can make markers different colors... Google it up!


A sample list of JSON encoded data of places to visit in Liverpool, UK. You can either make up a JSON list server side, or call it from a controller using JSONResult.

var data = [
  { "Id": 1, "PlaceName": "Liverpool Museum", 
    "OpeningHours":"9-5, M-F","GeoLong": "53.410146", 
    "GeoLat": "-2.979919" },
  { "Id": 2, "PlaceName": "Merseyside Maritime Museum ", 
    "OpeningHours": "9-1,2-5, M-F", "GeoLong": 
    "53.401217", "GeoLat": "-2.993052" },
  { "Id": 3, "PlaceName": "Walker Art Gallery", 
    "OpeningHours": "9-7, M-F", "GeoLong": 
    "53.409839", "GeoLat": "-2.979447" },
  { "Id": 4, "PlaceName": "National Conservation Centre", 
    "OpeningHours": "10-6, M-F", "GeoLong": 
    "53.407511", "GeoLat": "-2.984683" }

Using the jQuery each selector to iterate through the JSON list and drop marker pins.

$.each(data, function (i, item) {
            var marker = new google.maps.Marker({
    'position': new google.maps.LatLng(item.GeoLong, item.GeoLat),
    'map': map,
    'title': item.PlaceName

Make the marker-pin blue!


Put in some information about each JSON object - in this case, the opening hours.

var infowindow = new google.maps.InfoWindow({
    content: "<div class='infoDiv'><h2>" + 
      item.PlaceName + "</h2>" + "<div><h4>Opening hours: " + 
      item.OpeningHours + "</h4></div></div>"

Finally hook up an OnClick listener to the map so it pops up an info-window when the marker-pin is clicked!

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

And that's all there is to it! ... F9 to run, nothing more to see here, move along, opening hours on the map :)

(PS: If you found this article useful or downloaded the code, please let me know by giving a rating below!)

Image 1


  • 1st August, 2013 - Version 1 posted, image added
  • 3rd August, 2013 - Source added
  • 7th August, 2013 - Bad format display tags removed
  • 9th August, 2013 - Added relevant search tags


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


About the Author

Chief Technology Officer The DataWorks
United Kingdom United Kingdom
Allen is a consulting architect with a background in enterprise systems. His current obsessions are IoT, Big Data and Machine Learning. When not chained to his desk he can be found fixing broken things, playing music very badly or trying to shape things out of wood. He runs his own company specializing in systems architecture and scaling for big data and is involved in a number of technology startups.

Allen is a chartered engineer, a Fellow of the British Computing Society, and a Microsoft MVP. He writes for CodeProject, C-Sharp Corner and DZone. He currently completing a PhD in AI and is also a ball throwing slave for his dogs.

Comments and Discussions

QuestionIs your article stolen?? Pin
nadier93-Jan-18 19:45
Membernadier93-Jan-18 19:45 
AnswerRe: Is your article stolen?? Pin
Vincent Maverick Durano3-Jan-18 20:03
professionalVincent Maverick Durano3-Jan-18 20:03 
GeneralRe: Is your article stolen?? Pin
nadier93-Jan-18 22:33
Membernadier93-Jan-18 22:33 
GeneralRe: Is your article stolen?? Pin
DataBytzAI3-Jan-18 23:59
professionalDataBytzAI3-Jan-18 23:59 
PraiseGreat Pin
Mahsa Hassankashi16-Dec-17 4:14
MemberMahsa Hassankashi16-Dec-17 4:14 
QuestionMissingKeyMapError Pin
cassellwang24-Jan-17 21:43
Membercassellwang24-Jan-17 21:43 
AnswerRe: MissingKeyMapError Pin
DataBytzAI24-Jan-17 23:28
professionalDataBytzAI24-Jan-17 23:28 
GeneralMy vote of 4 Pin
Muhammad Shahid Farooq13-Aug-16 0:50
professionalMuhammad Shahid Farooq13-Aug-16 0:50 
GeneralRe: My vote of 4 Pin
DataBytzAI13-Aug-16 1:33
professionalDataBytzAI13-Aug-16 1:33 
PraiseThank you! Pin
Merve623-Feb-16 22:16
MemberMerve623-Feb-16 22:16 
GeneralRe: Thank you! Pin
DataBytzAI23-Feb-16 23:51
professionalDataBytzAI23-Feb-16 23:51 
Praisenice work, very easy to understand ! Pin
greens testmail14-Feb-16 18:39
Membergreens testmail14-Feb-16 18:39 
GeneralRe: nice work, very easy to understand ! Pin
DataBytzAI14-Feb-16 23:40
professionalDataBytzAI14-Feb-16 23:40 
QuestionHow to use a Postcode from a field Pin
Member 1090489624-Oct-15 7:29
MemberMember 1090489624-Oct-15 7:29 
AnswerRe: How to use a Postcode from a field Pin
DataBytzAI25-Oct-15 11:10
professionalDataBytzAI25-Oct-15 11:10 
Question"Download source code" Pin
Member 1191928829-Aug-15 21:21
MemberMember 1191928829-Aug-15 21:21 
QuestionDownload source code Pin
Member 1191928829-Aug-15 21:14
MemberMember 1191928829-Aug-15 21:14 
Question1000 Thanks bro! :D Pin
Misael Moneró Thompson30-Jun-15 17:17
MemberMisael Moneró Thompson30-Jun-15 17:17 
GeneralMy vote of 5 Pin
Misha_K.26-Apr-15 6:23
MemberMisha_K.26-Apr-15 6:23 
QuestionAdaptive zoom Pin
Laurentiu LAZAR23-Apr-15 3:46
MemberLaurentiu LAZAR23-Apr-15 3:46 

Is possible to adapt zoom in respect with the pinpoints displayed (e.g. if the coordinates are let say around the city centre to have a zoom around 14, if are in nearby cities to have 10, if are nationwide to have e.g. 6)?
I have a stored procedure that filter records in a table of Lat/Long according to radius of a given coordinate (let say current position), but I don't knowhow to sue this in MVC. I think that can be useful to what I want.
And also any hint about to calling in JS data from controller via JSON (instead of var Data)?

AnswerRe: Adaptive zoom Pin
DataBytzAI23-Apr-15 4:11
professionalDataBytzAI23-Apr-15 4:11 
GeneralRe: Adaptive zoom Pin
Laurentiu LAZAR23-Apr-15 5:54
MemberLaurentiu LAZAR23-Apr-15 5:54 
GeneralThanks Pin
ozgurgunes197828-Jan-15 7:53
Memberozgurgunes197828-Jan-15 7:53 
AnswerRe: Thanks Pin
DataBytzAI28-Jan-15 8:39
professionalDataBytzAI28-Jan-15 8:39 
QuestionBrilliant Pin
Member 1136125017-Jan-15 4:10
MemberMember 1136125017-Jan-15 4:10 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.