whoiskatrin whoiskatrin - 4 months ago 6
C# Question

JSON from js to MVC controller

today I'm trying to get JSON from my JS part of code and pass it to c# method.
The problem that I got null when I have passed the result to the current method.

Here is my JS part:

GMaps.on('click',
map.map,
function(event) {

markers.push(new Point(map.markers.length, event.latLng.lat(), event.latLng.lng()));


var index = map.markers.length;
var lat = event.latLng.lat();
var lng = event.latLng.lng();
map.addMarker({
lat: lat,
lng: lng,
title: 'Marker #' + index
});
console.log(JSON.stringify(markers));
});

function TestJSON() {

$.ajax({
url: "@Url.Action("ReturnJson","Home")",
type: "POST",
data: JSON.stringify(markers),
contentType: "application/json; charset=utf-8",
dataType: "json"
});
};


As you see from the code, in console I see that array of markers is not empty and after every new click I add a value to the array.
When I will locate all markers I want to save it, so I made a button for it.

Here is my data model:

public class TripPoint

{
public string Name { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }

}

public class TripRoute
{
public List<TripPoint> route = new List<TripPoint>();
}


It how looks like my html code:

<form>
<button type="button" value="Save your route " onclick="TestJSON()"></button>
</form>


And at last it how looks like the method which should get JSON string

[HttpPost]
public ActionResult ReturnJson(string json)
{
// **********************************
// PROBLEM HERE: json is null
// **********************************

TripRoute route = new JavaScriptSerializer().Deserialize<TripRoute>(json);
return new EmptyResult();
}


Please, help to find out why I get a null string.

upd.

Here is my route config

public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

routes.MapRoute(
name: "ReturnJSON",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "ReturnJSON", id = UrlParameter.Optional }
);

ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());
}
}

Answer

The items you are adding to the markers is with properties lat,long and title, but your view model (Which you are trying to serialize to) has different property names. So i suggest you to create a class with same property names

public class MarkerItem
{
  public string Title {set;get;}
  public decimal Lat {set;get;}
  public string Long { set;get;}
}

and since you want to send an an array of marker's, use a collection of the above class as your parameter. You do not need to use a string as parameter and deserialize it again. The Default model binder will be able to map the posted data to a list of MarkerItem class objects

public ActionResult ReturnJson(List<MarkerItem> markerItems)
{
    //do something with markerItems list
    // to do : Return something
}

I just noticed your routeconfig. You do not need the second route registration. Your default route registration is good enough.

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
    ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());
}