Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to include Google Maps in .Net Core?

I have a .Net Core application and in one of my views I want to have a Google Map in which I want to be able to draw dynamical polylines.

Index.cshtml

I have included a Google Map on my view as follows:

<div class="col-md-6 col-lg-6">
    <h3>My Google Maps Demo</h3>
    <div id="map"></div>
</div>

<script>
  function initMap() {
    var center = { lat: 55.92965249, lng: 12.47840507 };
    var map = new google.maps.Map(document.getElementById('map'), {
      zoom: 12,
      center: uluru
    });
  
    $.get()
    $.post()

    route.setMap(map);
  }
</script>

And in my _Layout.cshtml I have:

<script async defer
    src="https://maps.googleapis.com/maps/api/js?key=...api key...&callback=initMap">
</script>

All of this works as intended, but I am unsure of whether this is the proper way to show Google Maps in a .Net Core application?

Furthermore I want to be able to draw dynamical routes in my Google Maps implementation. This is done via the following code

var route = new google.maps.Polyline({
    path: routeCoordinates,
    geodesic: true,
    strokeColor: '#FF0000',
    strokeOpacity: 1.0,
    strokeWeight: 2
});

where routeCoordinates is a list of coordinates:

var routeCoordinates = [
    {lat: 55.92965249, lng: 12.47840507},
    {lat: 55.92941392, lng: 12.47832253},
    {lat: 55.92918626, lng: 12.47824027},
    ...
    {lat: 55.91474539, lng: 12.47145191},
    {lat: 55.91450191, lng: 12.47139283},
    {lat: 55.91425197, lng: 12.47134614}
]

All the above is of course done statically in my Index.cshtml.

So is there a better way to do this? And how would I go about adding and removing lines dynamically (hopefully) by using my Controller? I expect something like:

public async Task<IActionResult> Index()
{
    return View(await _context.Trips.ToListAsync());
    //context is my db
}

Right now it is not present but I will be getting a list of coordinates from my context through my EF implementation.

EDIT:

Since I posted this I have continued a bit, and I now have a PartialView that I want to load when clicking a table row:

MapPartialView.cshtml

@model IEnumerable<LngLat>

<div class="col-md-6 col-lg-6">
    <h3>My Google Maps Demo</h3>
    <div id="map"></div>
</div>

<script>
    function initMap() {
        var center = { lat: 55.92965249, lng: 12.47840507 };
        var map = new google.maps.Map(document.getElementById('map'), {
            zoom: 12,
            center: center
        });

        //$.get();
        //$.post();

        routeCoordinates = @Model;

        var route = new google.maps.Polyline({
            path: routeCoordinates,
            geodesic: true,
            strokeColor: '#FF0000',
            strokeOpacity: 1.0,
            strokeWeight: 2
        });

        route.setMap(map);
    }
</script>

And my:

Index.cshtml

// table header and so forth..
<tbody>
    @foreach (var item in Model)
    {
        <tr class="trips" data-id="@item.TripID" data-url="@Url.Action("ExpandMap", "Trip")">
            <td>
                @Html.DisplayFor(modelItem => item.DeviceID)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.StartTime)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Duration)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.StartLocation)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.EndLocation)
            </td>
        </tr>
    }
</tbody>

<div id="partialMap"></div>

And in my:

site.js

$('.trips').each(function (i, e) {
    var _this = $(this);
    var element = $(e).children('td');
    element.click(function () {
        //console.log("Clicked! " + _this.data('url') + " " + _this.data('id'));
        $("#partialMap").load(_this.data('url'), { id: _this.data('id') }, function () {
            $("#partialMap").slideDown('200');
        });
    });
    
});

And lastly my controller and the ExpandMap function:

TripController.cs

public IActionResult ExpandMap(int id)
{
    var trip = _context.Trips.SingleOrDefault(t => t.TripID == id);

    List<LngLat> routeCoordinates = new List<LngLat>
    {
        new LngLat() { lat = 55.92965249, lng = 12.47840507},
        new LngLat() { lat = 55.92941392, lng = 12.47832253},
        ...
        new LngLat() { lat = 55.91450191, lng = 12.47139283},
        new LngLat() { lat = 55.91425197, lng = 12.47134614}
    };

    string routeCoordinatesJS = JsonConvert.SerializeObject(routeCoordinates, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });

    return PartialView("MapPartialView", routeCoordinatesJS);
}

But when I run the code I get a:

Failed to load resource: the server responded with a status of 500 (Internal Server Error)
like image 251
Zeliax Avatar asked Nov 24 '16 13:11

Zeliax


1 Answers

You can export your context to a list of lat and lng

    public class LngLat
    {
        public double lat { get; set; }
        public double lng { get; set; }
    }


The build your list with data from your db and send it to the View():
public async Task<IActionResult> Index()
{           
    List<LngLat> routeCoordinates = await _context.Trips.Select(c=> new LngLat {lat = c.latitude, lng = c.longitude })

    //Serialize your routeCoordiamte with Json.Net
   string routeCoordinatesJs = JsonConvert.SerializeObject(routeCoordinates, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore })

    return View(routeCoordinatesJs);
}

In your View():

var routeCoordinates = @Model
like image 167
Yanga Avatar answered Oct 25 '22 09:10

Yanga