📜 ⬆️ ⬇️

ActionResult for all occasions

The farther into the "forest", the thicker the MVC framework. Here recently released a preview of the second version. Quickly acquainted with the possibilities, I was very happy. But then I remembered the simple and very interesting RoR opportunity, which is not yet (even in the plans) in MS MVC.
We are talking about the possibility of specifying an “extension” for the Action method and, thereby, determining the type of View.


First, consider an example. The ht_p: // localhost / Blog / Comments / 0 request returns an html page containing a list of comments to article number 0 on the blog. In this case, Blog is the name of the controller, Comments is the name of the method, 0 is the record ID.
The controller code will look something like this:

public class BlogController : Controller
{
public ActionResult Comments( int id)
{
var strings = new [] { "" , "" , "" }; // ,
return View(strings);
}
}

* This source code was highlighted with Source Code Highlighter .

')
Everything is simple!

And what to do if we need in addition to the html page to get a list of comments serialized in json? The easiest way is to create another method, call it, say, CommentsJson, and explicitly call the Json () method. For example:

public ActionResult CommentsJson( int id)
{
var strings = new [] { "" , "" , "" }; // ,
return Json(strings);
}


* This source code was highlighted with Source Code Highlighter .


Now we can get the json list at ht_p: // localhost / Blog / CommentsJson / 0.

Problem solved, disagree? Frankly, this code does not suit me. Firstly, duplication, and secondly, I don’t like the url that I’ll have to use later; thirdly, there’s no way to use the scheme in other methods.

In this case, the opportunity to create your own ActionResult will come to our rescue. We will try to solve the problem "in the forehead." Change the Comments method as follows:

public class BlogController : Controller
{
public ActionResult Comments( int id)
{
var strings = new [] { "" , "" , "" }; // ,
return new ComplexResult
{
Json = () => Json(strings),
View = () => View(strings)
};
}
}

* This source code was highlighted with Source Code Highlighter .


As you can see, the ComplexResult class must be inherited from ActionResult.
Let's try to implement it like this:

public class ComplexResult : ActionResult
{
public override void ExecuteResult(ControllerContext context)
{
object value ;
if (context.RouteData.Values.TryGetValue( "result" , out value ))
{
var result = value .ToString();
if (result.Equals( "json" , StringComparison.InvariantCultureIgnoreCase))
{
Json().ExecuteResult(context);
return ;
}
}

View().ExecuteResult(context);
}

public Func<JsonResult> Json { get ; set ; }

public Func<ViewResult> View { get ; set ; }
}


* This source code was highlighted with Source Code Highlighter .


Here it is necessary to explain: when processing the result, we check the presence of the string “result” in the list of values ​​obtained when parsing the query. Make sure that the user has sent the “json” line and run the user-defined JsonResult. If the string is not found or it is not equal to “json”, run the ViewResult. The logic is pretty simple.

In parallel, we will add lines to the routes configuration:

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

// route default
routes.MapRoute( "Result" , "{controller}/{action}.{result}/{id}" ,
new { controller = "Home" , action = "Index" , id = "" , result = "view" });

routes.MapRoute( "Default" , "{controller}/{action}/{id}" ,
new { controller = "Home" , action = "Index" , id = "" });
}

* This source code was highlighted with Source Code Highlighter .


Now we have the opportunity to get a json object by explicitly specifying it in the query string ht_p: //localhost/Blog/Comments.json/0. Or ht_p: // localhost / Blog / Comments / 0 - when we need html. And most importantly, we can easily use ComplexResult in other methods, without clogging the code with repetitive methods.

Fantasy suggests that in this way you can add other standard or non-standard (XmlResult, RssResult, etc.) to ComplexResult ActionResults. Perhaps we are waiting for this in the next versions of ASP.NET MVC.

The code is written, now excuses: I recommend using the code written in this note only to familiarize yourself with the features of the MVC framework, obviously - it is not safe, for simplicity, some checks and conditions are omitted.

Thanks for attention.

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


All Articles