Workflows in ASP.NET MVC - c#

As a learning exercise, I want to migrate an existing flash application to ASP.NET MVC. It has around 20 forms, and although it's mostly linear, there is some degree of alternate flows based on user decisions or data returned.
Could anyone point me in the right direction of how a controller would handle this? I don't want my views to have to figure out where they go to next.
Update
I think I may not be understanding the correct way of building this. I saw each controller as taking care of a different section of the app, and having a main controller being responsible for workflow.
If this is not the approach I should be taking, what is the best way of doing this?
Update 2
Would Areas in ASP.NET MVC 2 take care of this sectioning of the app? I really don't like the idea of having too many actions in one controller...

In general:
Controllers are usually a collection of actions that deal with a logically coherent chunk of the application ( hence why you often see UserController / OrderController etc etc ).
MVC applications should be built using PRG ( post - redirect - get ) which means you will have 2 actions for each form, one that will display the form and the second, with the same name but decorated with [AcceptPost], that will process the form and redirect the user to the appropriate location based on the result.
The simplest way to learn how this works and migrate your app over is model each form as a simple dto with no logic, build a view for each form and 2 actions.
Once you have the logic working in the controller, you may want to migrate it out into some form of service that can be injected into the controller.
Specifically for your workflows:
Each workflow should probably have it's own controller. It may be useful to model them using some form of state pattern ( depending on the complexity of the workflow ), and providing a result from each state transition that your controller can translate into a redirect to the next step in the workflow.

When a form posts to a controller action it is the controller action to decide what to do with the posted results and which view to render next or redirect:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult HandleFormSubmission(FormCollection col)
{
// do something with posted data
// redirect to /someOtherController/someOtherAction
// which could show some other form
return RedirectToAction("someOtherAction", "someOtherController");
}

I was struggling with the same problem (using Windows Workflow Foundation with ASP.NET MVC) and I blogged about it here
Maybe you'll find it helpful, sorry for pushing my own link

Related

How to separate the view and the controller in an ASP.NET application

I have an ASP.NET application that was developed by "programmers". This application contains all things which you should not do:
Hardcoded settings
Copy/paste anywhere (code not re-used)
Make a lot of small SELECT requests to the DB for each row instead of doing JOIN
Model, view and controller in one function
Etc.
Now, my goal is not to throw everything away and start over, but I want to separate different aspects of the MVC of the application. I do not want to start a new MVC project, I would like to evolve the existing solution into something modular.
For the controller, there is no problem, I can create classes that will manage DB connections, send mails etc. On the other hand I do not know how to separate the view and the controller.
The problem that traditional ASP pages myPage.aspx have an associated file myPage.aspx.vb and in this vb file there are both view management part(page elements, like dropdowns) and also the Business part (controller) which is executed on the button click.
I thought about making a call to a myPageControl.vb class that will contain the business part from the file myPage.aspx.vb, which will call the Model (db, mail, other).
(View: myPage.aspx.vb) -> (Control: myPageControl.vb) -> (Model: Db.vb, Mail.vb)
The problem is: how should I do to modify the page content from the controller, for example change a list value or display a text on it. I have to make a call to the View (to the other direction) and pass by parameter the class MyPage (.asp.vb)
I have already tried to find an answer to my question, but I've found only answers taking about MVC projects.
Does anyone have any idea how I should do it?
Seperation of Concerns was one of the main problems with webforms, and one of the advantages of MVC. In my opinion the best you could probably do is seperate the business logic into classes like you are doing now so code could be reused throughout the application, but completely "seperating" everything may require rebuilding the application as an MVC app.
The only answer I've found to this is to have the controller send the "data to bind to" to the page as XML. then all the page has is its page_load of course, and then a method to receive the XML and update itself from it. You can use smart naming structures so that you can do reflection and autobind from the xml to page elements.
Then on an action, have the page generate an xml of all the elements on it and their values, and send that through a "ProcessAction" method that determines the correct controller and calls the right method on the controller.
But as suggested, doing it over as an MVC project probably makes the most sense if that's the pattern you are going for. What I suggested works, but it will be as much or more work than just starting from scratch with MVC. Besides, remember that "support" for web forms is disappearing soon. It's not in (and won't be in) .NetCore, so it's days are numbered.

pattern best way to connect View to multiple Controllers?

I'm recently doing a purchase order program using the MVC pattern in C# (not ASP.NET web app, just a desktop program). Now the problem is that in the UI there are lots of buttons that will link to another section, let's say from the order page I can click and go to the inventory page. Each section of course have their own set of MVC.
How can I connect the button to other controller while maintaining abstraction? That is each view does not have to understand how the other controller works, or what parameters it requires to work.
There are a couple of design possibilities that comes to mind but I have no idea which one is better / simpler:
The dirty way: just put the references to all the required controllers in one view, but this way reduce abstraction.
Shared view space: each button is a different view that has their own controller, but then I need to have view manager of some sort.
Routing: pretty much like ASP. NET RedirectToAction, make a custom router that use common type (like string) to determine which controller and which action to perform
Custom button for each action: for each controller and each action I make a button class just for it. Then I need a way for the view to supply the required parameters to each button.
Any suggestion on what should I do?
What i think that you should for the "shared view" i.e create on shared view containing all of that buttons and their calls if this is not working for you then you can create a saprate calls of WebAPI in their controller to get your date in return.
I decided to use a modification to my 4th option, a factory pattern that creates all my buttons. The factory is given the references to all the controllers and initializes all the buttons accordingly.
The view only need this factory during construction and ask for any of the button it can produce.
This way the view doesn't need to know anything about the controller during construction. The controller also doesn't need to know the view at all.
Thanks for everyone sharing their opinion.

Using MVC3 with folder structure like regular ASP.NET

So I am reading about building MVC3 projects and there is one thing that seriously bugs me. The folder structure of the project in no way corresponds to the path of the HTTP request. There is a bunch of things I like and would want to use, but having a flat folder structure is not one of them.
Why is this a problem? Well, I see it becoming a problem when building a site with a heavy mix of content pages and various forms/dynamic pages (most of our sites are like that), which would typically be done by different people. It seem it would be too complicated for client-side developers to follow routing rules of dynamic pages and/or creating new ones.
What I would like to understand is if there is way to configure MVC3 application in such a way that:
it follows directory structure for finding controllers without explicit route map for each one
views live in the same folder as corresponding controller
routing magic still works for actions and parameters
For instance I'd like to have a request /fus/ro/dah/ to try to find DahController in the \webroot\fus\ro\dah\ folder and execute its Index action. If not found it would look for RoController with Dah action in the \webroot\fus\ro\ folder, etc.
It is entirely possible that MVC was not meant to be working this way at all and I am just trying to force a square peg into a round hole.
UPDATE:
Looks like I can drop a view file into the desired folder structure, and it will be executed. However layout would not work apparently because it is expecting a controller. Does this mean I have to create a controller for pure content pages? That is a pretty crappy design...
UPDATE 2:
Main issue right now is that creating "fus" folder means that MVC will not even attempt to look for FusController... not under "fus" folder, nor anywhere else. Is it possible to get around that?
For instance I'd like to have a request /fus/ro/dah/ to try to find
DahController in the \webroot\fus\ro\dah\ folder and execute its Index
action. If not found it would look for RoController with Dah action in
the \webroot\fus\ro\ folder, etc.
MVC is not designed for a particular need like this, it is a general framework for building applications using model-view-controller pattern.
If you can't bend the application for the framework you can bend the framework for the application and honestly MVC is very customizable. [As a proof, in the current project (migration from ASP to MVC) that I'm working we have models as xml and no classes also we are using XSLTs for rendering. With a little work we have created custom components like custom view engine, custom validation provider, custom model binder... to make the framework best fit for the application and it does]
MVC is not designed and not forces to use it as it is and you can customize/extend as much you want. In your case you may have to create a
custom controller factory (because you want to customize the way in which the controller is seleced),
custom view engine (because you want to customize where the view is placed)
and may be others.
For custom controller factory you have to extend the DefaultControllerFactory class. There are lot of articles you can find through Google that explains about how to create custom controller factories.
Depending upon the view engine you are using you have to extend the respective one. For ex. if you are using web forms then you have to extend the WebFormsViewEngine and it razor then RazorViewEngine.
For more info. check this link
http://codeclimber.net.nz/archive/2009/04/08/13-asp.net-mvc-extensibility-points-you-have-to-know.aspx
you can mixup Asp.net and Asp.net MVC. as LukLed said, MVC is convention over configuration pattern. if you follow the convention. you dont need to configure. you can check this link for mixing up the asp.net content with MVC3
Mixing Asp.net and Razor
I believe ASP.NET MVC is not meant to be used that way. While you can configure MVC to do it, it is better to keep standard /controller/action/parameters URL format. If you have complex website with many different functionalities, areas may be helpful http://msdn.microsoft.com/en-us/library/ee671793.aspx. Every area get its own set of controllers, models and views, so teams working on different parts of website won't disturb each other.
While it may sound convenient, that framework first searches for DahController and executes Index action, then searches for another one, I find it bad idea. URLs should be clearly defined and Fus controller with Ro action shouldn't just stop working, because someone created RoController with Index action.
Look into using Areas as well. I think that helped me get over my folder structure issues with MVC honestly. So i could use the base folder as my Home details, then i could have a 'Admin' area which was a separate folder, things like that.
How "regular ASP.net" do you want it to be? If you want to do "legacy" ASP.Net Web Forms mixed in with MVC, you certainly can - re: mixing MVC with "file based aspx" - aka "hybrid". At the end of the day, it's all ASP.Net.
This is a standard MVC Application generated by Visual Studio. I've added a folder somedirectory where I want to use the legacy folder/file.ext paradigm and have a default.aspx Web Forms file:
Can I navigate to it via http://foo.com/somedirectory? Yes.
Can I use "pretty urls" too? Yes
Vanilla Global.asax generated by VS, just added MapPageRoute:
....
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//using "pretty urls" - ordering your routes matter.
routes.MapPageRoute("theWebForm", "legacy", "~/somedirectory/default.aspx");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
so now I can navigate to it via http://foo.com/legacy
Just check the order of your routes, and perhaps plan on your naming conventions so you don't have "collisions"...
Hth....

MVC pattern implementation. What is the n-relation between its components

I'm working in a C# project and we are , in order to get some unity across the different parts of our UI, trying to use the MVC pattern. The client is windows form based and I'm trying to create a simple MVC pattern implementation.
It's been more challenging than expected, but I still have some questions regarding the MVC pattern. The problem comes mostly from the n-n relationships between its components: Here is what I've understood, but I'm not sure at all of it. Maybe someone can correct me?
Model: can be shared among different Views. 1-n relationship between Model-View
View: shows the state of the model. only one controller (can be shared among different views?). 1-1 relationship with the Model, 1-1 relationship with the controller
Controller: handles the user actions on the view and updates the model. One controller can be shared among different views, a controller interacts only with one model?
I'm not sure about the two last ones:
Can a view have several controller? Or can a view share a controller with another view? Or is it only a 1:1 relationship?
Can a controller handle several views? can it interact with several models?
Also, I take advantage of this question to ask another MVC related question. I've suppressed all the synchronous calls between the different members of the MVC, making use of the events and delegates. One last call is still synchronous and is actually the most important one: The call between the view and the controller is still synchronous, as I need to know rather the controller has been able to handle the user's action or not. This is very bad as it means that I could block the UI thread (hence the client itself) while the controller is processing or doing some work. How can I avoid this? I can make use of the callback but then how do i know to which event the callback comes from?
PS: I can't change the pattern at this stage, so please avoid answers of type "use MVP or MVVC, etc ;)
Thanks!
Model, View, and Controller are conceptual layers, not individual objects, so honestly it doesn't make a whole lot of sense to be thinking of them in terms of multiplicities. Nevertheless, I can try to approximate an answer for you.
A Controller returns a single result for a single action; that result may be an actual view or it may be something else. However, the Controller doesn't really actually have any interaction with the view; all it does is provide one or two pieces of information in its result: The name of the view that should be used and (optionally) the model used to populate. It's up to the View Engine to actually create and bind the view, which is a considerable departure from normal Smart Client UI logic.
A Controller may interact with several different pieces of the Model, or not interact with it at all in some cases; there is no rule for that side of the relationship. In an action result, a Controller has to give back either 0 or 1 instances of a "model", but this may not be the true Domain Model, it could be a View Model.
A View is generally bound to exactly one Model (or View Model), although in some cases a View might simply be content and therefore not bound to anything.
So, in the very crude UMLesque parlance:
Controller:Model = 0..* : 0..*
Controller:View = 0..* : 0..1 (request) or 0..* : 0..* (overall)
View:Model = 0..* : 0..1
This is all specific to ASP.NET MVC. If you were designing your own MVC implementation then obviously you could choose to implement it any way you like. Good luck implementing MVC in WinForms, though; Forms don't behave like Views at all, even patterns like MVP/MVVM are quite difficult (though not impossible, c.f. Microsoft's CAB/SCSF) until you move to WPF.
I´ve implemented the MVC pattern in C#. Don´t know very much about theory, or how it should be, or shouldn´t be. I just think that the pattern is the base idea, and then, you can use this idea in many different ways, depending on your own needs. I´ll tell you about my implementation, and hope it helps you.
**The Model**
Your description is pretty clear, so don´t have much more to said. Here is where I define my bussiness objects. I take advantage of this layer to include objects validation rules.
**The Controller**
In addition to handle the user actions and update the view, I have a Unit Of Work for each controller. I check that the objects in the view pass the validations (defined in the model layer) before commit changes in the Unit Of Work.
In my case, one controller can manage many models, and I like to have only one view in each controller.
Like a suggestion, I´d like to use my Framework with diferent UI, so I have an abstract implementation of Controller, and then I have specific controller implementations for different interfaces (WebForms, WinForms, ...).
**The Views**
In your case, we could call them, simply, the forms, the UI, ... I like to organize my desktop applications as if they were web applications, using tabs. One tab represents one controller, and so on, one view, and one or more models.
In conclussion, and in my case:
n models - 1 controller
1 controller - 1 view
--
n models - 1 view
You're probably over-thinking and over-formalizing it a bit.
Here's how I look at it:
Model: This is the actual thing that does real work.
Controller: This is the thing that sends inputs into the model, so it will do work.
View: This displays the results.
That's it. The easiest analogy to use is a console application - the app is the model, STDIN is the controller, and STDOUT is the view.
Extending that analogy, many GUI apps are built on top of command-line apps by attaching to STDIN/STDOUT. In that case, the things sending data to STDIN are the controller, the things taking data from STDOUT and putting on the window are the View, and the console app is still the model.
It's CS 101 again - input, processing, output. It's only trickier for a GUI app because the input and output are typically on the same window.
You (obviously) don't need to actually have a console app to do this - the separations can be done even in a single process. All the other weird wiring stuff that takes place is just whatever is needed to get this relationship between the parts to work. But the wiring isn't the important bit - the important bit is the separation of responsibilities and logical organization of the code.
So, whether 1 view must map to 1 controller, or any other orthognality issues are secondary. In fact, you should probably just do whatever your problem domain requires, but I'd (as typical) argue against over-eager generalization of code - IOW, don't mush things together that aren't really the same.

How to make my own Attribute tag?

I am using asp.net mvc 1.0. I know asp.net mvc has a couple attribute classes such as "AuthorizeAttribute", ActionFilter? and I think there is like 2 more.
So I have made my own AuthorizeAttribute but I am not sure if this is the right one to use again or if I even need to inherit any of these built in classes.
What I am trying to do this is. Every time a user hits an action method I want to check if there subscription length has expired. If it has return them to the page to buy a new subscription otherwise let them go on their way.
I don't want to add this to my Custom AuthorizeAttribute because I have one plan that is free and thus does not need this. So I was thinking of having another sort of tag like this and put it under the AuthorizeAttribute this way if they are not authorized they get caught by that one. If they are but there subscription they get caught by the new one.
So how should I go out building this?
Thanks
As for tutorials and samples, check out:
Understanding Action Filters
Logging with ASP.NET MVC Action Filters
ASP.NET MVC - Action Filters
ASP.NET MVC Action Filters
Custom Action Filter in ASP.Net MVC application
Hope those help a bit !
Your idea of building another ActionFilterAttribute is correct. Trick is to set the Order property on your filters and make sure they fire in the right order.

Categories