ASP.NET MVC - How to call void controller method without leaving the view?

Question background:

I am implementing some basic 'shopping cart' logic to an MVC app. Currently when I click a link - denoted as 'Add To Cart' on the screen shot below this calls to an 'AddToCart' method in the 'ProductController' as shown:

enter image description here

Product.cshtml code:

@Html.ActionLink("Add To Cart", "AddToCart")

'AddToCart' method in the ProductController:

public void AddToCart()
{
   //Logic to add item to the cart.
}

The issue:

Not an issue as such but currently when I click the 'Add To Cart' button on the ActionLink on the ProductDetail.cshtml view the page calls the 'AddToCart' method on the ProductController and gives a blank view on the page - as shown below. I want the view to stay on 'ProductDetail.cshtml' and just call the 'AddToCart' method, how do I do this?

enter image description here


Solution 1:

Basically @Html.ActionLink() or <a></a> tag uses get request to locate the page. Hence whenever you clicked it, you request to your AddToCart action method in ProductController and if that action method returns null or void so a blank or empty page is shown as you experienced (because or @Html.ActionLink() get request by Default).

So if you want to add your value to cart then call AddToCart method using ajax i.e:

HTML:

@Html.ActionLink("Add To Cart", "AddToCart", null, new { id="myLink"})

Jquery or Javascript:

$("#myLink").click(function(e){

    e.preventDefault();
    $.ajax({

        url:$(this).attr("href"), // comma here instead of semicolon   
        success: function(){
        alert("Value Added");  // or any other indication if you want to show
        }

    });

});

'AddToCart' method in the ProductController:

public void AddToCart()
{
   //Logic to add item to the cart.
}

Now this time when the call goes to AddToCart method it goes by using ajax hence the whole page will not redirect or change, but its an asynchronous call which execute the AddToCart action method in your ProductController and the current page will remains same. Hence the product will also added to cart and page will not change to blank.

Hope this helps.

Solution 2:

The answer of Syed Muhammad Zeeshan is what you are looking for, however you may return an EmptyResult.

public ActionResult AddToCart()
{
    //Logic to add item to the cart.
    return new EmptyResult();
}

According to this it has no impact on your code ASP.Net MVC Controller Actions that return void But maybe sometime you want to return data and then you could do something like this:

if (a) 
{
    return JSon(data);
}
else
{ 
     return new EmptyResult();
}

Solution 3:

There are many ways to accomplish what you want, but some of them require a lot more advanced knowledge of things like JavaScript than you seem aware of.

When you write ASP.NET MVC applications, you are required to have more intimate knowledge of how browsers interact with the web server. This happens over a protocol called HTTP. It's a simple protocol on the surface, but it has many subtle details that you need to understand to successfully write ASP.NET MVC apps. You also need to know more about Html, CSS, and JavaScript.

In your case, you are creating an anchor tag (<a href="..."/>), which when click upon, instructs the browser to navigate to the url in the href. That is why you get a different page.

If you don't want that, there are a number of ways change your application. The first would be, instead of using an ActionLink, you instead simply have a form and post values back to your current controller. And call your "add to cart" code from your post action method.

Another way would be have your AddToCart method look at the referrer header (again, part of that more subtle knowledge of http) and redirect back to that page after it has processed its work.

Yet another way would be to use Ajax, as suggested by Syed, in which data is sent to your controller asynchronously by the browser. This requires that you learn more about JavaScript.

Another option is to use an embedded iframe and have your "add to cart" be it's own page within that iframe. I wouldn't necessarily suggest that approach, but it's a possibility.