Click here to Skip to main content
11,641,081 members (60,046 online)
Click here to Skip to main content

Google Maps in MVC 4 with Custom InfoWindow

, 20 Aug 2013 CPOL 63.4K 6.2K 77
Rate this:
Please Sign up or sign in to vote.
A quick tutorial on using Google Maps in MS MVC 4.

Introduction

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.

Background

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="http://maps.google.com/maps/api/js?sensor=true" 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.

<style>
    .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:

@Scripts.Render("~/bundles/jquery") 
@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...
   </script>

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 () {
    Initialize(); 
});  

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!

marker.setIcon('http://maps.google.com/mapfiles/ms/icons/green-dot.png')

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!

marker.setIcon('http://maps.google.com/mapfiles/ms/icons/blue-dot.png')

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 () {
            infowindow.open(map, marker);
        });
    })
}

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

 

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

History

  • 1/Aug/13 - Version 1 posted, image added.
  • 3/Aug/13 - Source added.
  • 7/Aug/13 - Bad format display tags removed.
  • 9/Aug/13 - added relevant search tags 

License

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

Share

About the Author

AJSON
Engineer
United Kingdom United Kingdom
Architect/engineer, student, always learning and refactoring my wetware. Happiest tucking into a big bowl of c# or python sprinkled with a crisp topping of Javascript...started with a single ZX80 a lifetime ago, now happily explore, build and create on interweb scale...



  • 6 Oct 2014 - "Full Calendar – A Complete Web Diary System for jQuery and C# MVC" - article of the day on ASP.net


You may also be interested in...

Comments and Discussions

 
AnswerRe: Very nice your article! Pin
AJSON18-Jul-14 10:00
memberAJSON18-Jul-14 10:00 
Questionuseful Pin
utosw6-Dec-13 22:38
memberutosw6-Dec-13 22:38 
AnswerRe: useful Pin
AJSON7-Dec-13 2:20
memberAJSON7-Dec-13 2:20 
GeneralMy vote of 5 Pin
Mohit-CleverCues21-Oct-13 4:02
memberMohit-CleverCues21-Oct-13 4:02 
AnswerRe: My vote of 5 Pin
AJSON21-Oct-13 4:06
memberAJSON21-Oct-13 4:06 
QuestionChange View from Index to another Pin
Member 102522554-Sep-13 2:24
memberMember 102522554-Sep-13 2:24 
AnswerRe: Change View from Index to another Pin
AJSON4-Sep-13 2:39
memberAJSON4-Sep-13 2:39 
GeneralRe: Change View from Index to another Pin
Member 102522554-Sep-13 3:27
memberMember 102522554-Sep-13 3:27 
Ok, this makes me crazy.
The only thing I've changed to the code is to take away the info stuff and have a pure map.
I have added the map code both to my new own Map view but also to the default Index view.
When I start up with Index view as default in RouteConfig that view works fine but when click in menu to change to Map view, Map doesn't display.
So then I stop debugging and change RoutConfig default value from Index to Map.
And now Map works but when clicking in my menu changing to Index (Home), then that view doesn't work.
So it seems like it's only the default view in RouteConfig that works.

Can it be som refresh stuff for the view that one change/swap to after the default one? Javascript issue?

I saw that I missed when copying the Java script from your example. Now corrected and also added the marker stuff, everything is in there now, still same issue.

Have you tried to copy your example to another view than the default?

When locking at it it seems like the DIV / Placeholder / the space is there in the view that doesn't work but map is not displayed in it.

I'm using the default MVC4 mobile template and just add this stuff.

I have now tested the same with your code/example and that works fine, so I wonder where the difference is?!
br
/M

modified 4-Sep-13 10:21am.

GeneralRe: Change View from Index to another Pin
Hammer4All13-Sep-13 3:23
memberHammer4All13-Sep-13 3:23 
AnswerRe: Change View from Index to another Pin
AJSON14-Sep-13 2:13
memberAJSON14-Sep-13 2:13 
GeneralMy vote of 5 Pin
Member 212808430-Aug-13 23:25
memberMember 212808430-Aug-13 23:25 
QuestionUseful :) Pin
timeleft24-Aug-13 12:58
membertimeleft24-Aug-13 12:58 
AnswerRe: Useful :) Pin
AJSON25-Aug-13 1:29
memberAJSON25-Aug-13 1:29 
GeneralMy vote of 5 Pin
Robert J. Good20-Aug-13 9:56
memberRobert J. Good20-Aug-13 9:56 
AnswerRe: My vote of 5 Pin
AJSON25-Aug-13 1:28
memberAJSON25-Aug-13 1:28 
QuestionExcellent article. Pin
Murat Yalvaq7-Aug-13 13:49
memberMurat Yalvaq7-Aug-13 13:49 
AnswerRe: Excellent article. Pin
AJSON8-Aug-13 0:23
memberAJSON8-Aug-13 0:23 
AnswerRe: Excellent article. Pin
AJSON12-Sep-14 2:15
memberAJSON12-Sep-14 2:15 
GeneralMy vote of 5 Pin
DrABELL7-Aug-13 10:20
professionalDrABELL7-Aug-13 10:20 
GeneralRe: My vote of 5 Pin
AJSON7-Aug-13 10:40
memberAJSON7-Aug-13 10:40 
GeneralRe: My vote of 5 Pin
DrABELL7-Aug-13 10:44
professionalDrABELL7-Aug-13 10:44 
GeneralMy vote of 5 Pin
Simon Jackson7-Aug-13 4:38
professionalSimon Jackson7-Aug-13 4:38 
GeneralRe: My vote of 5 Pin
AJSON7-Aug-13 5:50
memberAJSON7-Aug-13 5:50 
GeneralMy vote of 5 Pin
Patrick Harris3-Aug-13 16:52
memberPatrick Harris3-Aug-13 16:52 
GeneralRe: My vote of 5 Pin
AJSON7-Aug-13 5:50
memberAJSON7-Aug-13 5:50 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150731.1 | Last Updated 20 Aug 2013
Article Copyright 2013 by AJSON
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid