How to organize controller class and action method? - asp.net-mvc

Suppose I am working on a Car Portal. To search a new car, the user provides the following information:
Brand
Model
ModelVersion
FuelType
Budget
Business Rules:
If user selects Brand only : Show brand list page with all models of selected brand
If user selects Brand and Model : Show Model List page
If user selects Brand + Model + Model version : Show model version details page.
if user selects Fuel type OR Budget : Show Brand list page.
Now I have two approaches to define controller and action.
Approach 1: One Controller class with multiple action method
Controller Class : CarSearchmanager
with following are Action Methods:
- SearchNewCar(int Barnd,int Model.......)
Depending on user selection this method will redirect control to following
action method:
- BrandListing(int BrandID......)
- ModelListing(int BrandID,intModelID.....)
- ModelVersionDetails((int BrandID,intModelID,int ModelVersionID....)
Approach 2: Multiple controller class
Controller Class : CarSearchmanager
Following are Action Methods:
- SearchNewCar(int Barnd,int Model.......)
Depending on user selection this method will redirect control to following
controller action method:
Then I will have separate controller class and action method for each of the pages like
bellow:
- BrandListing
- ModelListing
- ModelVersionDetails
I am very confused about how to organize the controller class and action methods. Is there any best practice kind of document? Please suggest one to me.

I do not think there is a defined best version. Define it in such a way that you feel more clean and organized. From my understanding of your requirement, i may define like this
BrandController
action methods
ListForFuleAndBudget(string fuelType,string budget)
List(string brandName)
ModelController
action method
List(string brand,string model)
Details(string brand, string model, string version)
Now if you want nice url where you do not want the action method names as ot is, (ex :details) you can define your pretty urls when registering your routes in global.asax, before the generic route definition.
routes.MapRoute("list", "model/{brand}/{model}",
new { controller = "brand", action = "List");
routes.MapRoute("list", "model/{brand}/{model}/{version}",
new { controller = "brand", action = "details");
//default route definition goes here
Now yoursitename/model/honda/camry will take the user to the list action method and
yoursitename/model/honda/camry/lx will take them to the details action method.

my suggestion is to have this in the same controller
Since this is a search functionality which will be used
In a similar context. Use method overloading and in the
Corresponding methods return the particular view.

Related

How to call action method using query string in mvc

Question: when new employee created I have to send mail to the admin. right now mail sending successfully but when admin clicks the link directly it should open the created employee partial view along with partial 1 and partial view 2 for your reference please find below the image.
i dont know how to do this one. right now directly i called the action method
Example:
it should call the following action method
//websitename/seachcountry
//websitename/listofemployee
//websitename/emplyesearchbyid
which is the best way to call from the email link.
Thanks.
To answer your question, to call an action using query string, your action should look like the following in your controller:
public ActionResult EmployeeInfo(string query)
{
// use query here
}
However, I suggest create an employee details action and view that would correspond to route like //websitename/employee/details/id.
This view must be tied to a viewmodel that contains all required info about the employee (including the data in partial views).

ASP.NET MVC Tuple

In my View i have to put two different Forms and i have to use two different ViewModels. So i decided to use Tuple.
View:
#model Tuple<pi.Models.AddNewMechanic,pi.Models.ExistingUser>
and I got two forms
But how can i recive it from View in HttpPost Controler?
I tried like that:
public ActionResult AddMechanic(Tuple<pi.Models.AddNewMechanic, pi.Models.ExistingUser> model) {}
but i got message it cannot find method with parameter, so how I have to implement it inside this method, but there is a question how?
I strongelly sugest you create a new Model and inside of your new model, you can put this two object. Take care to dont mix domain model and view model. Otherwise, you will have always this kind of problem.
Domain Model
- class a
- class b
View Model
- class AB
prop A, prop B
I suggest you do this by the book, which would be:
AddMechanic.cshtml has no special view model, but contains two partial views. This is your "page with two forms".
_AddNewMechanic.cshtml is the first partial view form, which has AddNewMechanic as view model.
_ExistingUser.cshtml is the second partial view form, which has ExistingUser as view model.
The form in _AddNewMechanic.cshtml posts to the AddNewMechanic action method, which takes an AddNewMechanic as parameter.
The form in _ExistingUser.cshtml posts to the AddExistingMechanic action method, which takes an ExistingUser as parameter.
Upsides:
No need for any Tuple weirdness.
You can keep your existing View Models.
Your action method parameters will not normally be null, so no need for weird null checks.
Easy to follow and understand your code.

ASP.NET MVC Routes: Conflicting action names with custom route

i all,
In a previous question, I asked how to define a custom route to handle the following URL:
http://www.example.com/User/Profile/Edit/{userProfileID}
I have a User object and a UserProfile object, but only a UserController that I want to be able to use for actions on both objects. I already have a method in UserController called Edit that handles edits on a User. But I also need a method for edits on a UserProfile. The answer to my routing question was the following route:
routes.MapRoute(
"ProfileleRoute", // Route name
"User/Profile/{action}/{userProfileID}", // URL with parameters
new { controller = "User", action = "Index" } // Parameter defaults
);
But given that custom route, where should I be declaring the edit action for a UserProfile, and what should it be called? It seems like I couldn't write another method in UserController called Edit because I already have one that handles User edits.
So I feel like I would end up with a need for two Edit actions to handle the following routes: "User/Edit" and "User/Profile/Edit". How do I get around this?
Thanks very much.
When the framework it's going to select what action to execute it first check the actions with the name required with a HttpPost ot HttpGet attribute that match the request, if not action is selected this way, then it select any action that match the name.
So, if you have two actions with the same name with no HttpPost or HttpGet attributes, you can't control with action is going to get executed.

How to design a complex form that requires search results from a different MVC controller

I want to create a form for creating an order. So I have an 'Order' controller. One of the first steps will be to select an existing person to send this order to.
I'm thinking the Create() action method on OrderController will put a new Order object in session. Then I'll need a link that will redirect to another controller, then return a customerID int to this Create() method.
I will have either a SearchController with a FindCustomer() action method, or a Search() action method on the CustomerController.
I have tried the first way. But what I am doing looks pretty messy. Especially considering that I'll need to do this at least one more time on this form, redirecting to the ItemsController to return items to add to the order.
What's the best way to design communication like this between controllers?
I'm not sure why you think you need other controllers for this. In your GET Create action, put the available Customers and Items in to ViewData, and then in your view put some controls for the user to select values.
Then they will be POSTed to your POST Create action, and you can bind & save it in your Order object. You could have a separate action for adding Items to the Order if that gets too complex. But it could still be on the same OrdersController.

How can I create 1 route with 2 differents user's access in ASP.NET MVC?

How can I do this: I have on page named "Schedule" and it can be accessed through 2 differente ways:
URL 1- www.bla.com/Admin/Schedule
URL 2- www.bla.com/Schedule
"URL 1" will be accessed by users with Admin previlegies and this View will show some Admin stuff, and users must be LoggedOn.
In the otherhand, "URL 2" will be accessed by users NOT LoggedOn and it will NOT show the admin stuff.
But, they are the same page, just with some differences depending on user's access.
I already have AdminController and I intend to put this "Schedule" View as part of this controller. As result, I know if I type "URL 1" it will work. But, if I type "URL 2"? Will I have to create a "ScheduleController" just to handle this?
I wonder if there is a way to resolve this by Global.asax, configuring the routing... I don't know...
Thanks!!!
You can map the /Schedule route to the /Admin/Schedule action from the Global.asax.cs like this:
routes.MapRoute(
"Schedule",
"schedule",
new { controller = "Admin", action = "Schedule" }
);
This will solve your immediate problem of wanting two separate routes resulting in the same action/view.
However, this will not solve your scenario properly. The main issue is that the identity of the logged on user is orthogonal to the route the request takes. In other words, you can't force the admin user to always hit the /Admin/Schedule route, they could just as well hit the /Schedule route and still would expect the same end result. Not only that, but doing it this way will prevent you from using the [Authorize] attribute on the Admin controller or the action to force the user to login and will have to implement custom logic checking which route the action was hit through and decide whether you want to force login or let the user through.
Thus, you have to make a decision:
you share the controller, action and the view and determine whether to show the additional information in the view based on the identity and the role membership of the logged on user (if any). You will have to change the name of the controller then, as /Admin will not reflect the new role this class has;
you share only the view and have two separate controllers and actions - Admin.Schedule and User.Schedule. You will have to put the view in the /views/shared folder and return the same view fromboth actions, potentially passing different model. You'll end up with two routes - /Admin/Schedule and /User/Schedule;
you have two separate controllers, actions and views.
In all three cases, you can still have the rule above pointing to the appropriate controller, if you want to have also the shortest /Schedule route.
Make the View shared and just render it from both controller actions. Pass the appropriate data via the model (or ViewData) so the View knows not to render the admin stuff when rendered from the non-admin controller action.
And, yes, create the Schedule controller. Make the routing simple and handle sharing the generation code on the back end.
AdminController
public ActionResult Schedule( ... )
{
Schedule sched = ... get model ...
return View("Schedule", new SchedViewModel {
Schedule = sched,
Admin = true
} );
}
ScheduleController
public ActionResult Index( ... )
{
Schedule sched = ... get model ...
return View("Schedule", new SchedViewModel {
Schedule = sched,
Admin = false
} ); }
Sounds like you don't really need a different URL if it's the same page. However if for some reason you still want to use 2 different URLs...
Url 1:
routes.MapRoute("ScheduleAdmin", "Admin/Schedule",
new
{
controller = "AdminController",
action = "Schedule"
});
Url 2:
routes.MapRoute("Schedule", "Schedule",
new
{
controller = "ScheduleController",
action = "Index"
});
You didn't make it clear what action you were using for the schedule controller so feel free to change that.

Resources