Fat ASP.NET MVC Controllers - asp.net

I have been reading about "Fat Controllers" but most of the articles out there focus on pulling the service/repository layer logic out of the controller. However, I have run into a different situation and am wondering if anyone has any ideas for improvement.
I have a controller with too many actions and am wondering how I can break this down into many controllers with fewer actions. All these actions are responsible for inserting/updating/removing objects that all belong to the same aggregate. So I'm not quiet keen in having a seperate controller for each class that belongs to this aggregate...
To give you more details, this controller is used in a tabbed page. Each tab represents a portion of the data for editing and all the domain model objects used here belong to the same aggregate.
Any advice?
Cheers,
Mosh

For all your tabs you can use one action, that have an tab parameter, that indicate what data you need to return.
The controller job is to cast this string tab into enum type variable. Then the tab will be send to the repository, and the repository job is to return data in response to the tab value.
The controller should do its job through to services: Input Validator and Mapper.
The mapper service job is to map the user input (typically strings) into actual typed value (int, System.DateTime, enum types, etc).
The validator job is to check that the input is valid.
Following this principles should keep your controllers really tiny.

If you wanted something simple and easy I'd suggest just splitting up the controller into partial classes based on the tabs. Of course, it's still a fat controller there's just some obvious separation between the various tab functionalities.

Related

ASP.NET Using one controller from another

I am creating an mvc project, for simplification i have two entitys: Movies and MoviesGenre.
I want to display a list of genres and the amount of movies each of them contains.
Now i have a problem with the design. I am not sure who is responsible for it. I solved that by creating a method in MovieController that returns the amount of movies by genre id and created a method on the MoviesGenreController that select all the genres and uses the MovieController(By instantiating an object) method to get their count.
That doesn't seems like good design to me. Which controller is responsible for this? Do I maybe need to create an extra controller for this logic? Thanks.
You need a data layer project which will manage the access of each controller to the underlying database.
I would suggest the following design:
create a library project (DataLayer) project which connects to the database.
Potential methods exposed:
List GetAllGenres();
List GetMoviesByGenre()
You can either inject the DataLayer as a service or just simply allocate a new object in each controller ctor. This is more like a personal preference... The DI approach is more flexible a more in line with the DotNetCore architecture.
Both MovieController and MovieGenreController should use the methods from the DataLayer.

Bind/map response to more than one object

I am new to MVC. I have a controller ActionResult that has various incoming requests from various parties. I want this ActionResult to figure out what type of request it is, validate it, and perform several RedirectToAction.
My problem is that while I know how to bind a single model/object to an ActionResult and have the framework automatically map the variables from the request to that model's properties, I don't know how to achieve the same "automapping" functionality when I need to map the same request to several models that are completely separate from each other inside a single ActionResult. I am unable to determine what models are contained inside the request until I map them and validate them, by checking if the models' properties are not null.
Any thoughts?
You should really create different Actions. Since the models that are passed in are different you cannot bind them to the same action.
Of course, what you could do is create different action methods, and from there on just call a single method that contains all of your logic
If you have access to the different model classes you could create an interface that they implement, and use this interface as the model type in your controller method.
Then you could create a custom model binder and do your checking of properties there.

Does Spring MVC require copy/paste of Entity to FormObject?

I'm developing my first Spring 3 webapp. In Spring 2, we used to have formBackingObject load data from the database, then let Spring binding update some of the fields, and then onSubmit would persist those changes.
In Spring 3 it seems I have two options:
Let the user edit 100% of the persistent object. This would mean that the object's ID would need to be a hidden field
Create a form object which holds the editable data, and then map that onto the persistent object on submit
The first option is not truly an option, we cannot let the user edit all fields, and we'd rather not present data in hidden fields where anyone capable of pressing F12 can alter the values.
The second option seems like a decent design approach. However, it appears that it requires to essentially clone every editable, persistent class.
#Entity
public class Company {
private String uuid; // not editable!
.. 30 other properties, 2 are not editable
}
public class CompanyForm {
.. 28 of above properties
}
and then some mapping mechanism with lots of
public void map(CompanyForm cf, Company c) {
cf.setName(c.getName());
.. 27 other set(get())
}
I'm praying this is not the "as designed" approach of Spring's MVC binding. However, all tutorial I've found so far are terribly trivial and implement option 1 from above. Does anyone have some suggestions for implementing option 2?
Thanks, Simon
DataBinder API
Note that there are potential security implications in failing to set an array of allowed fields. In the case of HTTP form POST data for example, malicious clients can attempt to subvert an application by supplying values for fields or properties that do not exist on the form. In some cases this could lead to illegal data being set on command objects or their nested objects. For this reason, it is highly recommended to specify the allowedFields property on the DataBinder.
You can use it together with option 1
A pragmatic way would be to just ignore the non editable fields on the update statement.
I have actually circumvented this in the past by using a #ModelAttribute annotation and detecting the PK on the request, if you do it this way Spring will use the object that is returned from #ModelAttribute and automatically copy the submitted object to it.
It's kind of a hack and not obvious to someone who comes in to maintain the code though.

ASP.NET MVC routing based on data store values

How would you tackle this problem:
I have data in my data store. Each item has information about:
URL = an arbitrary number of first route segments that will be used with requests
some item type = display will be related to this type (read on)
title = used for example in navigation around my application
etc.
Since each item can have an arbitrary number of segments, I created a custom route, that allows me to handle these kind of requests without using the default route and having a single greedy route parameter.
Item type will actually define in what way should content of a particular item be displayed to the client. I was thinking of creating just as many controllers to not have too much code in a single controller action.
So how would you do this in ASP.NET MVC or what would you suggest would be the most feasible way of doing this?
Edit: A few more details
My items are stored in a database. Since they can have very different types (not inheritable) I thought of creating just as many controllers. But questions arise:
How should I create these controllers on each request since they are related to some dynamic data? I could create my own Controller factory or Route handler or possibly some other extension points as well, but which one would be best?
I want to use MVC basic functionality of using things like Html.ActionLink(action, controller, linkText) or make my own extension like Html.ActionLink(itemType, linkText) to make it even more flexible, so Action link should create correct routes based on Route data (because that's what's going on in the background - it goes through routes top down and see which one returns a resulting URL).
I was thinking of having a configuration of relation between itemType and route values (controller, action, defaults). Defaults setting may be tricky since defaults should be deserialized from a configuration string into an object (that may as well be complex). So I thought of maybe even having a configurable relation between itemType and class type that implements a certain interface like written in the example below.
My routes can be changed (or some new ones added) in the data store. But new types should not be added. Configuration would provide these scenarios, because they would link types with route defaults.
Example:
Interface definition:
public interface IRouteDefaults
{
object GetRouteDefaults();
}
Interface implementation example:
public class DefaultType : IRouteDefaults
{
public object GetRouteDefaults()
{
return new {
controller = "Default",
action = "Show",
itemComplex = new Person {
Name = "John Doe",
IsAdmin = true
}
}
}
Configuration example:
<customRoutes>
<route name="Cars" type="TypeEnum.Car" defaults="MyApp.Routing.Defaults.Car, MyApp.Routing" />
<route name="Fruits" type="TypeEnum.Fruit" defaults="MyApp.Routing.Defaults.Fruit, MyApp.Routing" />
<route name="Shoes" type="TypeEnum.Shoe" defaults="MyApp.Routing.Defaults.Shoe, MyApp.Routing" />
...
<route name="Others" type="TypeEnum.Other" defaults="MyApp.Routing.Defaults.DefaultType, MyApp.Routing" />
</customRoutes>
To address performance hit I can cache my items and work with in-memory data and avoid accessing the database on each request. These items tend to not change too often. I could cache them for like 60 minutes without degrading application experience.
There is no significant performance issue if you define a complex routing dictionary, or just have one generic routing entry and handle all the cases yourself. Code is code
Even if your data types are not inheritable, most likely you have common display patterns. e.g.
List of titles and summary text
item display, with title, image, description
etc
If you can breakdown your site into a finite number of display patterns, then you only need to make those finite controllers and views
You them provide a services layer which is selected by the routing parameter than uses a data transfer object (DTO) pattern to take the case data and move it into the standard data structure for the view
The general concept you mention is not at all uncommon and there are a few things to consider:
The moment I hear about URL routing taking a dependency on data coming from a database, the first thing I think about is performance. One way to alleviate potentialy performance concerns is to use the built in Route class and have a very generic pattern, such as "somethingStatic/{*everythingElse}". This way if the URL doesn't start with "somethingStatic" it will immediately fail to match and routing will continue to the next route. Then you'll get all the interesting data as the catch-all "everythingElse" parameter.
You can then associate this route with a custom route handler that derives from MvcRouteHandler and overrides GetHttpHandler to go to the database, make sense of the "everythingElse" value, and perhaps dynamically determine which controller and action should be used to handle this request. You can get/set the routing values by accessing requestContext.RouteData.Values.
Whether to use one controller and one action or many of one or many of each is a discussion unto itself. The question boils down to how many different types of data do you have? Are they mostly similar (they're all books, but some are hardcover and some are softcover)? Completely different (some are cars, some are books, and some are houses)? The answer to this should be the same answer you'd have if this were a computer programming class and you had to decide from an OOP perspective whether they all have a base class and their own derives types, or whether they could be easily represented by one common type. If they're all different types then I'd recommend different controllers - especially if each requires a distinct set of actions. For example, for a house you might want to see an inspection report. But for a book you might want to preview the first five pages and read a book review. These items have nothing in common: The actions for one would never be used for the other.
The problem described in #3 can also occur in reverse, though: What if you have 1,000 different object types? Do you want 1,000 different controllers? Without having any more information, I'd say for this scenario 1,000 controllers is a bit too much.
Hopefully these thoughts help guide you to the right solution. If you can provide more information about some of the specific scenarios you have (such as what kind of objects these are and what actions can apply to them) then the answer can be refined as well.

ASP.NET MVC View information stored in a data-store

I'm looking for some advice on storing views in a data-store (database, file, other) and display them based on routing data, all using ASP.NET MVC 2 and ASP.NET Routing.
For example, I'd like to be able to display different views based on the following route data:
/{country}/
/{country}/{area}
But in the same vein I'd like to display:
/{planet}/
/{planet}/{satellite}
All are based on strings, and the data isn't fixed. So based on the number of segments maybe, use that as the selection criteria into the data-store...additionally, I may not know the segments up front, so they'd all be dynamic.
I'm was hoping we could get a few different methods together here, as kind of a reference for all - I'm sure some methods won't suite everyone...
So, how would you do it?
Branislav Abadjimarinov suggested a Controller Factory which could be used to do the look-up and display the page dynamically. I like this idea, what do you think?
There is no way for MVC to understand from this url's which route to choose. You have to make the routes more specific. For example:
/planet/{planet}/{satelite}
/country/{country}/{area}
You also have the option to define your own controller factory. The controller factory decides which controller to instantiate based on the route. So you can put some custom logic in it like - check if the {planet} parameter exist and if yes instantiate Planet controller else instantiate Countries controller.
This Post could be really helpful for you.
Remember you always can add a new routing rule : )
Just like this

Resources