Search code examples
asp.netajaxasp.net-mvcasp.net-corenettopologysuite

How to send data from ajax to a base controller method that runs on every visited page


I want user's latitude and longitude to be updated on every page visited. In order not to duplicate things, I created a base controller where I also implemented the onActionExecuting which allows the method to run every time on every action from the derived controllers, but I can't figure out how to pass the latitude and longitude parameters since they are only passed from the browser through an Ajax call.

public class BaseController : Controller
{
    protected readonly UserManager<ApplicationUser> _userManager;

    public BaseController(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        base.OnActionExecuting(context);
        UpdateLocation(latitude, longitude); //How do I pass these parameters from Ajax?
    }

    public void UpdateLocation(double latitude, double longitude)
    {
        var user = _userManager.GetUserAsync(User);
        if (user != null)
        {
            user.Location = new Point(latitude, longitude) { SRID = 4326 };
            await _userManager.UpdateAsync(user);
        }
    }
}

I placed this script in the layout. It retrieves the location data and sends it to the action method.

<script>
$(document).ready(function () {
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(showPosition);
    }
    else {
        console.log($`Geolocation + {} not supported by browser.`);
    }
});

function showPosition(position) {
    var postData = { 'latitude': position.coords.latitude, 'longitude': position.coords.longitude };
    $.ajax({
        url: 'Base/UpdateLocation',
        contentType: 'application/json; charset=utf-8',
        type: 'GET',
        data: postData,
        dataType: 'json',
        success: function (data) {
            console.log(data);
        },
        error: function (request, data) {
            console.log(data);
        }
    });
};
</script>

Solution

  • I didn't need to implement the onActionExecuting method. I changed the UpdateLocation to an action method. Though there is no need to create a base controller, I could simply put the action method in one controller and it will be called from any controller as long as the views of that controller inherit from the layout view where the location script is placed.

    public class BaseController : Controller
    {
        protected readonly UserManager<ApplicationUser> _userManager;
    
        public BaseController(UserManager<ApplicationUser> userManager)
        {
            _userManager = userManager;
        }
    
        public async Task<JsonResult> UpdateLocation(double latitude, double longitude)
        {
            var user = await _userManager.GetUserAsync(User);
            if (user != null)
            {
                user.Location = new Point(latitude, longitude) { SRID = 4326 };
                await _userManager.UpdateAsync(user);
            }
            return Json($"Latitude: {latitude}, Longitude: {longitude}");
        }
    }
    

    Then updated the location script in the layout.

    <script>
        $(document).ready(function () {
            if (navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(showPosition);
            }
            else {
                console.log($`Geolocation + {} not supported by browser.`);
            }
        });
    
        function showPosition(position) {
            var postData = { 'latitude': position.coords.latitude, 'longitude': position.coords.longitude };
            $.ajax({
                url: "@Url.Action("UpdateLocation", "[DerivedControllerName]")",
                contentType: 'application/json; charset=utf-8',
                type: 'GET',
                data: postData,
                dataType: 'json',
                success: function (data) {
                    console.log(data);
                },
                error: function (request, data) {
                    console.log(data);
                }
            });
        };
    </script>