Where should I place sub-structures within a MVC controller - asp.net-mvc

I am trying to build a controller that will enable the user to add/remove subcontent to an item.
Think of it like a document where you can add different types of sections, like headlines, paragraphs, images etc. (they each have their own attributes so they are in seperate tables in the SQL)
My question is where should I put the code to handle the different types of subsections within this "document controller"?
They are all attached to this "document"/entity through database relations, but should I make a "crudl" controller for each type or should I do a base kinda crudl and then let them all inherit this?
I've looked into "Models" and "service layers" - is that the right way to do it?
I am still rather new with MVC, using C# and ASP.net I was hoping for someone to give me a hint in the right direction.
Nb. please let me know if I should rephrase the question. Didn't know what to ask to get the right answer here.
Specs: I use EF 4.x and MVC3 will upgrade to latest when available, if needed.
In hope of some clever answers or guidance. Thanks in advance people. And yes, I have tried to Google too. Don't know what to search for, so I come here.

where should I put the code to handle the different types of subsections within this "documentcontroller"?
The code for this would ultimately go into a controller action which you then handle and update the database accordingly. There are multiple ways of doing this, you could be generic e.g.
[HttpPost]
public ActionResult AddSection(string type)
{
switch (type)
{
case "HEADING":
// add new heading to database
case "PARAGRAPH":
// add new paragraph to database
}
return View(type);
}
Or you could be specific e.g.
[HttpPost]
public ActionResult AddHeadingSection()
{
// add to db
return View("Heading");
}
[HttpPost]
public ActionResult AddParagraphSection()
{
// add to db
return View("Parapgraph");
}
The above is just really pseudo code to give you a rough idea of how you could do it with minimal effort. IN a real life situation you will probably be posting extra information along with it e.g. AddHeadingSection(HeadingModel model). It's really up to you how you go about implementing this.
Also, you might want to consider using AJAX over full postbacks it would make your app a bit slicker.

Related

ASP.NET MVC - Dynamic Url routing to Layout View

Firstly, I don't expect to be handed an answer on my plate, however any examples you think will help me will be readily received! I am mainly struggling with how to phrase my question due to being unfamiliar with the terminology and therefore, have not found many suitable resources as of yet.
I have a .net core 2 mvc application. On one page "home/categories" I have a list of items from a database. I wish to click on one of these items for example, tents, and pass a subset of data to a generic layout view that will take data from my model I have just passed in and display a list of products.
I would like the url to be home/categories/tents. I would be using this generic view for many other categories.
I have come across articles about URL Routing. Is this what I need to be looking at to get my solution?
If not URL Routing, should I be looking at a solution involving passing parameters? For example, I see urls containing, eg, categories/?=tents?=summertents. ( I do not know what this method is called, or whether it is suitable. )
Thank you for any help.
You could definitely combine both methodologies. I would say using the URL Routing to get you to home/categories/tents and from there if you want to further filter results use parameters (home/categories/tents?=summertents).
I think this gives a clean look and ability to manage filtering parameters easier.
public class ProductsController : Controller
{
//GET /Products/Categories
public void Categories()
{
//return your list
}
//GET /Products/Tents?season=summertime
public void Tents(string? season)
{
//return a list of tents in a particular season
}
}

ASP.NET MVC: Is "views must be dumb" correct statement?

Most of the good references for MVC on web strongly suggest "views must be dumb". It should not contain any logic. This does not seems valid when I try to implement it.
Some of my views display only first name of student and some of them display only last name and some of them display full name. My database (and POCO and DTO) store name in separate components. I see best place to format the name is view.
My view changes on some actions on client side without hitting server. Example, on clicking some button, it hides some part of view and shows other and disable some controls. Or another button opens new window and takes some inputs and validates it. This input is never sent to server; it is only useful for some client side activities.
I have validations on server side. But just to save the hit to server, I also validate on client side.
Data binding with KnockoutJS.
Based on data (start and end date) received from server, I generate table on client side to display sections of that period slicing 1 hour each. This is something scheduling like GUI. I need to do date and time calculations in view to achieve this. When I was in stone age (ASP.NET WebForms), I was generating this table on server side; I know you are shocked. I shifted it to JS for performance.
In SPA, view hold most of the logic by fetching only necessary data from server through AJAX.
I can put many other similar examples here those force me to put some logic in view. Considering that view still holds logic and use of JS is increasing day by day, can we still say "views must be dumb" is a correct statement?
Some details explaining the same with respect to points above will help.
Notes:
Though my question is based on ASP.NET, I am expecting answers referencing to ONLY MVC as a design pattern; no matter what technology I use. So please do not suggest what is another way to do validations. Points above are just to note some of the cases where logic is necessary in view.
There might be something wrong in how I am implementing above points. But My only point is that, use of JS (and putting logic in views as a result) is increasing.
Everyone is welcome to contradict above points in case I am implementing it wrong way; just do not redirect entire discussion that way.
Edit 1:
#kayess: Yes, I have Models as well as ViewModels and this is obvious in MVC. Server logic that is strongly related to specific view and cannot be reused is put in ViewModels. Major part of domain logic which is reusable is put in Models. Even after having ViewModels, there are many things those I will prefer to do on client side. About narrowing the question, the basic answer to this question will be "Yes" or "No". Other details will be just to support the answer. I do not think this will attract opinions as there must be something about MVC views that I have not fully understood. The one answering the question just need to point that out to me.
I think generally by "views must be dumb" means specifically the server side part of the views. Having TypeScript/JS in a view is perfectly normal. I wouldn't however expect to have dozens of lines of C# in the view that is fetching records from a database.
However, having some very simple logic such as the following is pretty common:
#{
if(user.IsLoggedIn)
{
<span>You have new messages!</span>
}
else
{
<span>You need to login to view messages.</span>
}
}
However server side view code shouldn't get much more complicated than that because that breaks down the whole point of separation concerns and having appropriate abstractions and design patterns etc, and just becomes unmaintainable.
See also: Microsoft documentation on "Adding a View"
May it be any technology there are set of theories supporting different concepts, like you said view should be dumb there are advocates of model should be dumb.
Idea here is let your view model take care of the manipulation if any needed, and let your view refer to view model. So that change is centric.
And I believe you are alredy doing that.
Although this is an old question and has an accepted answer, I want to add some points not covered in any answers.
I think you are overlooking cases where more logic can be pushed to your domain model. For example, you mention the concept of "Name" and that you must use conditional logic in your views to decide whether to show first, last or full name. I have a class called Name in my domain model. It incorporates the logic of FirstName, LastName and FullName like so:
public class Name
{
public Name(string firstName, string lastName)
{
this.FirstName = firstName;
this.LastName = lastName;
}
public string FirstName { get; }
public string LastName { get; }
public string FullName
{
get { return $"{this.FirstName} {this.LastName}"; }
}
}
In my UI I have have ViewModels with the whatever name property I need. When I convert my domain models to view models my conversion logic tells the ViewModel which property to use. If I need FullName I use Name.FullName. If I just need FirstName, I use Name.Firstname. At no point do I need to put conditional logic about names in my views.
In addition, you can use custom helpers, formatters and extensions to encapsulate reusable logic for views. For example, I have utilities to format phone numbers, addresses etc, so that I do not have to put this logic in every view that needs it. I also have a paging module in my UI that encapsulates paging so that I do not have to have paging logic in my views other than to call the pager.
Partial views are also helpful. For example, from the accepted answer, I would put the following in a partial view and just call it in each view, rather than repeating the conditional logic it in every view:
#{
if(user.IsLoggedIn)
{
<span>You have new messages!</span>
}
else
{
<span>You need to login to view messages.</span>
}
}
My point is there is a lot you can do to move logic out of views to keep them dumb.

ASP.NET WEB API Multiple Interfaces

I am designing ASP.NET WEB API service with two interfaces. First interface is read-only and second one is admin interface (to be used with MVC app) with full CRUD support. Does anyone know where I can get more information on such setup, any tutorials, walk thought, sample design document?
Also does it worth splitting these into two interfaces or keep them in same? But problem is that in read-only I expose 2-3 properties for every object while for admin there are 10-15?
Similar setup for WCF or design spec will do.
If I understand what your wanting to do, may I suggest rather than having one URL, i.e. \dataStuff\dataView split off into another view, maybe \dataStuff\edit\ which only admin's have access to, can be done like so:
[Authorize(Roles = "Administrators")]
public ActionResult edit()
{
return View();
}
then next to each data element that your viewing add the following to ONLY admin's through use of User.IsInRole
#foreach (var item in Model.dataTable)
{
#*
write a value from the data table here
*#
#Html.ActionLink("edit", "edit").If(User.IsInRole("Administrators"))
<br/>
}
obviously you don't have to display your data like this, I'm just showing that you add to the end of each element of the database an edit ActionLink IF the user is admin.
This allows your admin to view data like a user and also have the added functionality they need. Code re-use is better than a single view which has two states, Admin and non Admin.
Sorry if this isn't the best explanation, fairly new to MVC
Seems like this concept is sometimes called CQRS.
Sample: http://martinfowler.com/bliki/CQRS.html

Purpose of viewmodel in controllers when data already present

What is the point in using a viewmodel when all the relevant data is already available through the parameter in the signature of the controller? I've seen a lot of examples similar to this:
public ActionResult Index(BasicPage currentPage)
{
var model = new BasicViewModel { Heading = currentPage.Heading, Body = currentPage.MainBody, MyBlock = currentPage.MyBlock };
return View(model);
}
Why not just send in the "currentpage" in this example directly to the View? Is there something that is considered bad practise by doing like that?
The above was a general question for asp.net-mvc. I'll add a question about Episerver as well here as well and if I'm lucky someone can answer that as well.
When looking through the Alloy site done with MVC I also saw similar behavior like above where a viewmodel is created in all controllers, why not just send in the Page that is sent into the controller directly to the View? It seems like an unnecessary step to create the viewmodel? Most likely I'm missing some important point here =)
The idea behind viewmodels is that they are optimised for presentation. If you use domain objects you end up having to put logic into the view itself to control the way things are displayed. Putting logic into the view is poor design so the viewmodel gives you some flex so that you have this logic managed in a more appropriate place.
In addition, you can make your viewmodel simpler, only including the fields that are required for the specific view.
Your code example is not a good idea I agree. But having a view model is a good pattern. You might not need it right away but having a view model available and in place is a good option to have for upcoming additions. I would go with Joel's concept from his MVC templates: http://world.episerver.com/Download/Items/EPiServer-CMS/EPiServer-7---CMS/EPiServer-7-MVC-Templates/

How to update Model when binding to a ViewModel?

I have an [HttpPost] action method signature like this:
[HttpPost]
public ActionResult Edit(ExistingPostViewModel model)
{
// Save the edited Post.
}
Now, in the past (when i didn't use ViewModels, e.g R&D), i had an implementation of an Edit method like this:
[HttpPost]
public ActionResult Edit(Post model)
{
var existingPost = repo.Find(model.Id);
TryUpdateModel(existingPost);
repo.Save(existingPost);
return RedirectToAction("Success", existingPost.Id);
}
Which worked great.
But i'm confused how to adapt the above to the ViewModel approach.
If i do this:
TryUpdateModel(existingPost)
With my ViewModel approach, not much happens. No errors, but nothing is being updated because MVC won't know how to update a Post from a ExistingPostViewModel (before it was Post -> Post).
Now, i'm using AutoMapper. So i thought i could map from the ViewModel to the Post, then save the post.
But then im basically overriding everything. Which i don't want to do and defeats the point of the cut down ViewModel.
Can anyone un-confuse me?
This seems like a really common scenario, and i am totally stumped as to how people solve this. I can only see 3 possible solutions:
Don't use a ViewModel in the HTTP POST. As i said i did this in the past for R&D and it works, but now i see how my View's have evolved (validation, simplicity), and i can't compromise that just for the sake of this problem.
Don't use TryUpdateModel. Possibly, but then how would i merge in the changes?
Use left-to-right. Ugh. But at the moment this seems to be the way im leaning.
Someone please give me solution #4! :)
BTW, i'm using ASP.NET MVC 3, Razor and Entity Framework.
I actually ran into this exact same issue in a project I'm currently working on. As much as I wasn't a fan of it, I ended up doing the left to right approach and manually mapping my viewmodel data back to my entity.
The only nice thing about this approach is it does give you more control. Since I started using more compound viewmodels, where you actually have fields from more than one entity in your viewmodel, it started making more sense to do things this way.
I'm also using AutoMapper, and you're absolutely right, it does get awkward when you're trying to do a simple update operation. Wish I had some super clever workaround for you, but the "old fashioned way" seems to get the job done best for the work I've been doing.
Not sure if this will help, but it is working for me. I have my underlying domain table as a Visitor Object. My viewmodel contains the Visitor Object plus a couple of IEnumerables for dropdowns.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int id)
{
Visitor Visitor = new Visitor();
Visitor = db.Visitors.FirstOrDefault(v => v.VisitorID == id);
UpdateModel(Visitor, "Visitor");
db.SaveChanges();
return RedirectToAction("Index");
}
The UpdateModel works off my viewmodel because of the "Visitor" string telling it what values to compare.
For simple things where you don't have to run any controls prior to implementing the update what you are doing is okay (db.get(), and then update).
When things get complicated, you have to load the entity, and then select and apply user's changes from the view model, property by property. In those cases, you end up writing Update methods, which gets the new data as input, and then you load the existing entity, then compare states, and take the required actions based on the view model data. Actually in this case, probably you wont have an Update method but will have behaviors, like CancelPost, AddComment, EditPost (which also logs the edit reason), AddTagsToPost etc.

Resources