⬆️ ⬇️

ASP .NET MVC 3. Ajax.ActionLink as an image on the example of adding to favorites with an asterisk on habrahabr.ru

This article is dedicated to creating a link with a picture using the Ajax.ActionLink helper method, or rather the Extension to the Ajax.ActionImageLink method, which we will create.



First, a summary of Ajax, ASP .NET MVC 3, and their sharing.



AJAX (Asynchronous Javascript and XML - “asynchronous JavaScript and XML”) is an approach to building interactive user interfaces for web applications, which consists in “background” browser data exchange with a web server. As a result, when updating data, the web page does not reload completely, and web applications become faster and more convenient.



ASP .NET MVC is a web application creation framework that implements a Model-view-controller ( MVC ) pattern based on ASP .NET technology.

')

There are several Action methods for using AJAX in ASP .NET MVC 3, but we are interested in Ajax.ActionLink , so more about it:



Ajax.ActionLink



Ajax.ActionLink - a method that returns a link generated depending on the parameters passed, a click on which will send an asynchronous request to the server and determine the further behavior of the page.

There are a total of 12 options for overloading this method — the input parameters that can be passed to use it are discussed below:



To use the Ajax features in the MVC 3 project, we need to include the following files, which, by default, are located in the / Scripts folder:





Formulation of the problem



It is required to create a link in the form of an image (in our case, an asterisk), clicking on which will cause an asynchronous request to the server, and after receiving the answer, it will be updated (changing the image, the tooltip):



image



Considering the opportunities Microsoft provides us with the ActionLink ActionLink Ajax helper, we conclude that without a bike, they are not enough, so we need our own helper. Let's get started



1. Create an empty ASP .NET MVC 3 project



image



In the View engine specify Razor.



image



2. Add a HomeController and a view for the Index method



image



Select ~ / Views / Shared / _Layout.cshtml as master page for our presentation



image



And so, now we need to create an Extension method for our Ajax helper.



3. Create the Extension method Ajax.ActionImageLink



Add a core folder to the project root and a new static class Extensions.cs in it



image



Read more about creating extensible methods here .



We proceed directly to creating an expanding method. And so, for the basis of our link with the image we take the HTML markup and styles of habrahabr.ru, then the contents of the container will be represented by two states:

<div class="favourite"> <a class="add" title="  " href="#"></a> </div> <div class="favourite"> <a class="remove" title="  " href="#"></a> </div> 




Cutting off all unnecessary, we come to the fact that the container (the object to be changed is UpdateTargetId) will be a div, and our method will have to return HTML markup in the form of a link with a changing class and title.



* Then the author thought for the first time, and realized that all this is solved without expanding methods by means of the following code :

 @Ajax.ActionLink(" ", "Hello", "World", null, new AjaxOptions() { }, new { @title= Model.inFavourite? "  " : "  ", @class = Model.inFavourite? "add" : "remove" }) 


but deciding that it would be too easy, and having noticed a little, he complicated his task . *



Cutting off all unnecessary ... Adding too much, we come to the fact that the container (UpdateTargetId object to change) will be a div, and our method will have to return HTML markup in the form of a link containing the image with the changing title and path to the image.

 <div id="favourite"> <a href="/Home/AddOrRemoveFavourite"> <img src="/Content/images/star-off.png" title="  " /> </a> </div> <div id="favourite"> <a href="/Home/AddOrRemoveFavourite"> <img src="/Content/images/star-on.png" title="  " /> </a> </div> 


Note:

You can use different methods to add / remove entries to your favorites, but in this article, one method will be used - AddOrRemoveFavourite .

And so, the framework of our expanding method is presented below:

  public static IHtmlString ImageActionLink(this AjaxHelper helper, string actionName, bool inFavourite, AjaxOptions ajaxOptions) { } 


Input parameters are:

  1. actionName - the name of the controller method (AddOrRemoveFavourite);
  2. inFavorite - a sign of whether the entry has already been added to favorites;
  3. ajaxOptions - request execution parameters.


To create HTML markup for our image, use the TagBuilder class:

 var builder = new TagBuilder("img"); builder.MergeAttribute("src", String.Format("/Content/images/star-{0}.png", inFavourite ? "on" : "off")); builder.MergeAttribute("title", inFavourite ? "  " : "  "); 


To create a link, use the standard Ajax.ActionLink method:

 var link = helper.ActionLink("[replaceme]", actionName, routeValues, ajaxOptions).ToHtmlString(); 


and then add a link text replacement to the content of our HTML img element:

 return new MvcHtmlString(link.Replace("[replaceme]", builder.ToString(TagRenderMode.SelfClosing))); 


As a result, our Extensions.cs class will look like this:

  public static class Extensions { public static IHtmlString ImageActionLink(this AjaxHelper helper, string actionName, bool inFavourite, AjaxOptions ajaxOptions) { var builder = new TagBuilder("img"); builder.MergeAttribute("src", String.Format("/Content/images/star-{0}.png", inFavourite ? "on" : "off")); builder.MergeAttribute("title", inFavourite ? "  " : "  "); var link = helper.ActionLink("[replaceme]", actionName, inFavourite, ajaxOptions).ToHtmlString(); return new MvcHtmlString(link.Replace("[replaceme]", builder.ToString(TagRenderMode.SelfClosing))); } } 


If you add a call to our extending method to the view (after specifying the @using directive MVC3_AjaxActionImageLink.Core ), the following HTML markup will be generated:

 <a data-ajax="true" data-ajax-mode="replace" data-ajax-update="#favourite" ref="/Home/AddOrRemoveFavourite"> <img src="/Content/images/star-on.png" title="  " /> </a> 


or

 <a data-ajax="true" data-ajax-mode="replace" data-ajax-update="#favourite" href="/Home/AddOrRemoveFavourite"> <img src="/Content/images/star-off.png" title="  " /> </a> 


It remains to add only a div, pictures of stars, a method call in the view, and the AddOrRemoveFavourite method itself, but I would like to dwell on the latter in more detail.



4. Adding the AddOrRemoveFavite method to the controller



In general, the method that handles an asynchronous request returns a value, be it a string, a number, JSON data, etc., but in our case, we will need to return the HTML markup of the new element that our extension method generates. Alas (or fortunately) in ASP .NET MVC 3 there is no possibility to call our extending method on the server side (in the controller method) and therefore we will not be able to generate markup without duplicating the code itself in the controller method (otherwise, one of the fundamental principles of MVC- DRY ).



However, from the controller's method, we can return a call to Partial View, which initiates a call to our extending method, which in turn will return HTML markup.



Let's get started



4.1. Add a Partial View with a call to an expanding method.



Add the folder folder Partial in the Views folder. In Partial add folder Favorites .

Add the View to the Favorites folder by selecting Create as partial view and indicating the name AddOrRemoveFavourites_PartialView



image



We add directives to the contents of the added Partial View:

 @using MVC3_AjaxActionImageLink.Core @Model bool 


and the call of our method itself:

 @Ajax.ImageActionLink("AddOrRemoveFavourite", (bool)Model, new AjaxOptions() { UpdateTargetId = "favourite" }); 


Note. To simplify the details, the model in this article will be a static variable of type bool.



The contents of Index.cshtml now assigns the call to the expanding Partial View method and looks like this:

 @using MVC3_AjaxActionImageLink.Core @model bool @{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h2>Index</h2> <div id="favourite"> @{ Html.RenderPartial("/Views/Partial/Favourites/AddOrRemoveFavourites_PartialView.cshtml", Model); } </div> 




4.2. Add an asynchronous AddOrRemoveFavite request processing method to the controller and associate with the model



In order to return our Partial View, you need to specify in the return a call to the PartialView method, passing the path to the first parameter. In addition, since we save the state in a primitive way through a static bool variable, we will transfer it as a model to both our View. The final version of our HomeController.cs class is presented below:

  public class HomeController : Controller { public static bool inFavourite = true; public ActionResult AddOrRemoveFavourite() { if (Request.IsAjaxRequest()) { inFavourite = !inFavourite; // TODO: Add or remove favourite return PartialView("/Views/Partial/Favourites/AddOrRemoveFavourites_PartialView.cshtml", inFavourite); } return View(); } public ActionResult Index() { // TODO: Check, if row is already in favourites return View(inFavourite); } } 




5. What is left?



The final stage will be the addition of the images folder with star-off.png and star-on.png images, as well as the connection of the script for working with AJAX in ASP .NET MVC 3:

 <script src="../../Scripts/jquery.unobtrusive-ajax.min.js" type="text/javascript"></script> 


We try.



image



we click



image



Conclusion



image



So, what have we all done in this article and learned:





Note



The name of the method and the principle of building the link as an image was taken from the project Stephen Walthe's Contact manger project

Source: https://habr.com/ru/post/134126/



All Articles