Why you should not use Linq in a view

Somewhere I had to use the linq operator to select a result set from my model, which the controller returned to Index ActionResult. for this, I googled โ€œhow to use linq in razor view modeโ€ and I get the result and my application works correctly, but I see some recommendations that say โ€œDo not use Linq in the viewโ€. Why shouldn't we use it, however is it possible? And if I do not want to use this solution?

This is my request:

@using System.Linq @{var lst = (from x in item.Showtimes select x.ShowtimeDate).Distinct();} @foreach (var showTimeItem in lst) { <option value="@showTimeItem">@showTimeItem</option> } 

UPDATE

This is my index controller

 public ActionResult Index() { MelliConcert.Models.MelliConcertEntities db = new Models.MelliConcertEntities(); var listOfConcerts = (from x in db.Concert orderby x.ID ascending select x).Take(15).ToList(); return View(listOfConcerts); } 

And I use it in the view as follows:

 @model IEnumerable<MelliConcert.Models.Concert> @foreach (var item in Model) { @if (item.OpenedForFirst == true) { //... } //Some Codes @using System.Linq @{var lst = (from x in item.Showtimes select x.ShowtimeDate).Distinct();} @foreach (var showTimeItem in lst) { <option value="@showTimeItem">@showTimeItem</option> } } 

My linq statement put in this loop. What should I do?

+4
source share
4 answers

There is nothing wrong with using LINQ in a view as such. The problem is not that you are using LINQ, the problem is that you are doing this:

 @{var lst = (from x in item.Showtimes select x.ShowtimeDate).Distinct();} 

At any time when you need to declare and set a variable inside your view, perhaps this is an indication of the need to change your model. For this purpose, your view model must have a property for this. Something like that:

 public IEnumerable<SomeType> DistinctShowtimes { get { return (from x in item.Showtimes select x.ShowtimeDate).Distinct(); } } 

Then the LINQ point in the view becomes controversial, since all you need is:

 @foreach (var showTimeItem in Model.DistinctShowtimes) { <option value="@showTimeItem">@showTimeItem</option> } 

UPDATE (in response to your updated question):

Now the problem (albeit a bit smaller) is this:

 @model IEnumerable<MelliConcert.Models.Concert> 

While this works, it limits. And what you experience is a limitation. You ask yourself: "How can I return more than one look?" The answer is to create a custom view model for this view. Right now, your view is tied to listing Concert objects. This is normal if all this is needed. But it turns out that not everything is needed. It has some common logic that requires a bit more. Thus, you create a custom view model. Something like that:

 public class ConcertsViewModel { public IEnumerable<Concert> Concerts { get; set; } // other properties, methods, anything } 

Then in the action of your controller, you return one of them:

 public ActionResult Index() { using(var db = new Models.MelliConcertEntities()) { var concertsModel = new ConcertsModel(); concertsModel.Concerts = (from x in db.Concert orderby x.ID ascending select x).Take(15).ToList(); return View(concertsModel); } } 

(Also note the use of the using statement, which should always be used when using IDisposable resources.)

So, now your view still receives a list of Concert objects, but it is packaged into a custom view model to which you can add additional features needed for this view. Then, in your opinion, change the model declaration:

 @model MelliConcert.Models.ConcertsViewModel 

(Itโ€™s assumed that you put it in the Models namespace. Depending on the size of your application, you might want to bring the view models into your own namespace. I donโ€™t often use the Models namespace in the actual application for the main business objects, so our projects are more likely everything is structured in very different ways. This should make you go, but you will want to make sure that your problems are carefully separated.)

Then, in the view code, you can refer to what you need from this object. Therefore, if you need to access the list, instead of just calling something like @foreach (var item in model) , you would @foreach (var item in model.Concerts) .

+6
source

I think in this case the argument would be to make the maximum amount of processing on your model before returning it to the view.

So, why not return the various views to the view, and then just skip them?

The only problem with your current setup is that it can undermine the spirit of MVC, which was supposed to separate the problems. The presentation should not use any logic that needs to be verified (or as little as possible). By keeping logic in models and controllers, you simplify unit testing, and views are easier to read by the developer.

EDIT Hey @ samangholami , you can return multiple objects to a view using a class. Create a class called "PAGENAMEViewModel" or something similar and create a property for each value that you want to return. For instance:

 public class MovieViewModel { public string MovieName { get; set; } public IEnumerable<string> Actors { get; set; } public IEnumerable<ShowTimeRecord> Showtimes { get; set; } public class ShowTimeRecord { public string TheaterName { get; set; } public string TheaterAddress { get; set; } public DateTime ShowtimeDate{ get; set; } } } 

Then return your complex model as follows:

 public ActionResult Index() { MovieViewModel model = myMovieHelper.GetMovieData(); return View(model); } 
+2
source

In addition to possibly resolving the issue, you may also have a performance issue that may be more difficult to diagnose.

If your LINQ query is somehow connected to the database through some kind of ORM or something like that, following the results, you can create a problematic script N + 1.

Moving him from the view may not interfere with him, but at least puts him somewhere, which is more noticeable.

+1
source

I believe that since it does not comply with the principle of separation of concerns , which is the fundamental concept of MVC. By executing this request in a view, you take business logic with you.

This has nothing to do with Linq itself. For example, you can execute the Linq statement to execute OrderBy . This is normal, because it is not business logic, it is the correct viewing operation (for example, ordering data into a table).

0
source

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


All Articles