Surface Controller or Custom Controller in Umbraco 7? - c#

History
I'm a Web Forms developer with some .NET MVC experience, new to Umbraco and learning as I go.
So far I've been following the Umbraco documentation and videos to get set up which means all my controllers inherit from a "Controller Base" with common functions included, which in itself inherits from SurfaceController.
Recently however, I have noticed some bloggers and external reference material referencing RenderMvcController in the base class instead of SurfaceController - now the Umbraco documentation is unclear on the real differences between the two, nor which situations you should use them in.
The Question
Is there a clear and distinct difference between the imagined usage scenarios for a Surface Controller - inheriting from Umbraco.Web.Mvc.SurfaceController, and a Custom Controller - inheriting from Umbraco.Web.Mvc.RenderMvcController?
Thanks!

The documentation for the SurfaceController is here: http://our.umbraco.org/documentation/Reference/Templating/Mvc/surface-controllers
In a nutshell, the SurfaceController is used for helping to interact with views. So for example you could post a form to a surface controller. Or you could write a child action to a view with a SurfaceController
RenderMvcController is used purely for routing to published pages. So you could sub-class RenderMvcController in order to 'hijack' requests to published pages of a specific Document Type. See here http://our.umbraco.org/documentation/Reference/Templating/Mvc/custom-controllers.

To further clarify based on Digbyswift's answer:
SurfaceController = APIs or form targets (that then redirect)
RenderMvcController = custom logic to build a model or select a view for a content item (based on Document Type and, optionally, template)

Related

Adding a controller to NopCommerce

I am writing my own Payment method for NopCommerce (for Datacash to be precise, if somebody can point me towards a Datacash implementation of IPaymentMethod for NopCommerce that would also answer my question).
The documentation provided by NopCommerce for doing this is great, and that is what I am using as my reference, but I am very new to MVC, and the first step is to create a new controller.
I understand that, in regards to MVC, you have models, views and controllers. The model is to do with how the data for your website is modelled, the view is what you see (your HTML etc) and the controller is the programming logic behind what you see.
In any MVC Hello World Application I have done so far, you usually have a folder for your models, one for your views and one for your controllers, as shown below:
However, NopCommerce looks like this:
So my question is in which folder do I put the controller I am about to create (or does it even matter)?
Thanks
One observation: it looks like you didn't download the source version of nopCommerce, which does indeed have "Controllers" folders:
On the nopCommerce downloads page (http://www.nopcommerce.com/downloads.aspx), look for the version "with source code", if you're looking to do customization of any sort.
You don't have to but it is best/wise to.
The convention like you said is to have a View, Model and Controller.
So create a Controller folder, and you can either put your Controller class directly in the folder or do the better thing and create a NOPCommerceController folder so it looks like:
Controller/NOPCommerceController/SomeController.cs
Nice and clean.
You should create your controllers and models inside your plugin project:

Curious about MVC Controllers?

Just a quick question, when you create a new controller for a new MVC ASP.Net app how does it know which controller to use. More specifically, given you create a new controller and you call it SockController in order to use said controller I would navigate to http://mywebapp/sock. How did the web app know that /Sock/ is linked to SockController? Is there a mapping somewhere ? Or if not what happens when if you call omit controller from the name when creating it, ie call it SockCont.
Note: I am not a Web Dev im just curious so please don't post links to page with tons of text, im looking for a short simple answer.
ASP.NET Routing extracts the name of the controller from the URL by getting the Route Value and then appending "Controller" to the end. So "/home/" returns "HomeController".
ASP.NET then uses reflection to go through every class in the project's assembly (or referenced assemblies) to find a class that inherits from System.Web.Mvc.Controller and is called "HomeController". It then uses the default, parameterless constructor to create an instance of it.
It then matches the Route action to a method of the controller.
This process is called "Dispatch" and similar patterns are seen in PHP, Ruby-on-Rails, etc, except that dynamic languages like those have different ways of resolving class names to actual objects (CakePHP uses Class auto-loading bindings to locate the class definition, for example).

Partial class for controller

Is it possible to create a Partial class for the controller in MVC?
Reason : I have a controller which contains too many code. This controller contains the code for different reports and due to too many code it reduces the readability of the code. I want to keep controller name same for all reports so I want to distribute code for the different reports.
If i can do any other way than do let me know.
Thanks
Alok Shah
Yes you can use a partial class - the compiler just merges them all up a compile-time to produce one.
However, you mention you want to 'distribute' code - if the code is to go into multiple projects then partials are not going to help.
You can instead create base controller classes (that inherit from System.Web.Mvc.Controller in a class library project, with the necessary action methods, and then simply use routing to route similar urls to different controllers. Here's a link to the Asp.Net Tutorial 'Creating Custom Routes' which might be useful for that. I hightly recommend looking through the rest of the tutorial if there are other core aspects of MVC you're not sure about. It doesn't cover everything, but it does the basics.
A web application that needs to use those then simply has its own controllers inherit from those redistributable ones. Even better, you can now create extensibility points through virtual methods etc if there are elements of these reports which different web apps might need to customise.
So "Reports/Customers" could route to a CustomerReportsController and "Reports/Orders" could route to an OrdersReportsController:
routes.MapRoute("CustReports",
"Reports/Customers/{action}",
new { controller = "CustomerReports", action = "Index", id = "" } );
routes.MapRoute("OrderReports",
"Reports/Orders/{action}",
new { controller = "OrdersReports", action = "Index", id = "" } );
This is the most simplistic approach to this problem - but I think using Areas (link is to MSDN walkthrough) would most likely also be applicable, in which case you might not need to use routing at all because the default route would probably do it all.
Of course!
Partial classes are a feature of the C# language and bare no relation to MVC or any other framework you may be using.
Yes. Partial classes are really just a feature of the language, and the compiled class is a regular .NET class like any other.
I would suggest though that you split the controller into multiple controllers, to ensure proper separation of concerns (having a class that is so big you need to split it up into multiple files will surely smell bad.)
"If I can do any other way than do let me know"
How about:
Abstract away the "doing" parts to various report generators for the discrete report types, all of which conform to an Interface. These report generators will be classes sat outside of the MVC tier of the application.
Clean up the controller so that the dependencies (Report generators) are injected in the constructor, using Ninject, StructureMap or Castle Windsor
Clean up all of the report generation code out of the controller and into concrete implementations of the Report generator abstractions
You will then not need to split up your controllers into separate classes. The downside is that this will take a reasonable amount of time to conceptualize and implement, but you'll end up with a better codebase.

Change the Location of the Controller inside the Project structure

I found this Post (How to extend where MVC looks for views) about changing the location of the View.
I was wondering if there's something similar for changing the location of the controller.
I just want to change the location of the class inside project and don't want to affect the url.
For example Instead of placing the Controller into
MyMvcProject\Controllers\
MyController1.cs
MyController2.cs
MyController3.cs
I want to achieve something like
MyMvcProject\MyGroup1\
MyController1.cs
MyController2.cs
MyMvcProject\MyGroup2\
MyController3.cs
and also support Areas:
MyMvcProject\Areas\MyGroup3\
MyController4.cs
Is it possible to achieve this? And if yes, where can I find documentation about it?
You can do what you want, and it doesn't require any special configuration, because ASP.NET MVC does not care about where you put your controllers. First, controllers are located using reflection, so the name of the folder where you put your controllers is irrelevant. Controllers are searched by type name and optionally by namespace (for disambiguation). You can even have controllers in separate projects/assemblies. As long as the controller ends up in an assembly in the bin folder then it's searchable by the framework.
As mentioned above, you'll need to create a controller factory to support your custom resolution. Here's an example:
http://develoq.net/2010/custom-controller-factory-in-asp-net-mvc/
As others have already stated you need to do one of the following:
Derive from IControllerFactory interface and provide an implementation of the CreateController and ReleaseController methods.
Derive from DefaultControllerFactory and override the default behaviours.
Here are some links to get you started:
Custom controller factory in ASP.Net
Inside the ASP.NET MVC Controller factory
Dive deep into MVC - IControllerFactory
Also, if you're willing to spend a bit of money I would also recommend the book Pro ASP.NET MVC 3 Framework as this explains almost every aspect of how the MVC framework can be customised (including an example on how to create a custom controller factory - the source code for which can be freely downloaded from the publishers website).
I think it is impossible to do this. ASP.NET MVC have defined the convention that we have to follow.
Controllers are in Controllers folder, views are in Views{ControllerName}\
I believe you cannot change the convention unless you create your own ControllerFactory.
If you really want to do that, just implement IControllerFactory interface (or try to derive from DefaultControllerFactory).
Then your Application_Start register your controller factory using ControllerBuilder.Current.SetControllerFactory method.
Look at the ControllerFactory documentation and to the MVC source code for details.
What you're asking and what your example shows are two different things; depending on which one you want to achieve, you may or may not need to do any work.
There are two requirements for a class to be a controller in the MVC Framework:
It has to have a class name of Name + "Controller"
It has to have a parameterless public constructor.
Your sample "normal" MVC layout is actually not valid:
MyMvcProject\Controllers\
MyController1.cs
MyController2.cs
MyController3.cs
Those classes wouldn't be found by MVC because they don't have the correct name, regardless of which folder they are in.
If all you want to do is change the namespace/folder names, that "just works", assuming you name them the same as the appropriate route segment(s):
MyMvcProject\MyGroup1\
Page1Controller.cs
Page2Controller.cs
MyMvcProject\MyGroup2\
Page3Controller.cs
MyMvcProject\Areas\Area1\
Area1Page1Controller.cs
This walkthrough (written for MVC 2 but works just as well in MVC3) shows you how to support Areas with the default controller behavior.
If you actually want to name them SomethingController1 or SomethingElseController5, or otherwise change the route -> classname mappings, then you do need to implement a custom ControllerFactory, and inject it into the MVC pipeline.
There are plenty of examples on the web on how to do this, including the one posted earlier.

Difference in MVC & MVP interms of code in c#

when we search Google for difference between MVC and MVP then thousand of article is available but i read few but they are not showing difference in terms of coding sample. so if anyone knows any url from where i can see a sample code for both MVC & MVP implementation then please tell me the url. i want basically small sample code by which shown the difference through coding flow in c#. i hope i am very much clear what i am looking for.....i need code same code one with mvc coding flow and another with MVP. i am not asking for theoretical explanation.
I also don't have sample code on my blog post "MVVM vs MVP vs MVC: The differences explained" but I do have a section for each architecture that discusses how to implement them using words. I will describe it here.
MVP requires a few implementation details
Each view must implement an interface for the view (eg IUserEditView for editing users). This interface contains functions for things that the presenter might need to do (eg, showUsers(IList users), displayMessage(String errorMsg)
A presenter is created for each view. It contains functions that the view will need to call (eg, saveNewUser(User user), selectedUserChanged(User user))
An instance of the presenter is created in the view's codebehind. When view events occur, appropriate messages are forwarded to the the instance of the presenter. eg, when the save button is clicked, all the user details are forwarded to the presenter in the form of a new user....myPresenter.saveNewUser(new User(txtUserName.text, txtPassword.text))
When the instance of the presenter is created in (3), the view is passed as an argument to the constructor. This way, the presenter can reference the IUserEditView from (1)
That is the meat of MVP. You will probably need to implement the mediator pattern and have all the presenters inherit from base presenter. This way, presenters can send messages to each other without having to reference each other explicitly which is important (eg, if a new user is added, maybe you need to update a related view like users online).
MVC is a bit more tricky.
The controllers have a method of selecting which view is displayed. This could be referencing just a dictionary of instances of all the views but a better way is to have some class outside the controller manage the details and then the controller can just select the view with something like ShowView("UsersView", listOfUsers). Note the separate class can be a base class, or a factory, helper
A method of forwarding actions from the views to appropriate controllers. With the web, you just can determine the controller & method from the request url (eg, http://www.mysite.com/mycontroller/method, www.mysite.com/Users/AddNew/). For other systems, you will have to implement a class to manage the messages, or just directly forward them to an instance of the controller in the view. I've only used MVC with the web so I'm not so sure about the last point.
Because of (2), the view is now able to trigger actions in the controller. When it does so, the controller modifies the model (the implementation of this will depend on the details of your model).
Updates to the model get sent to the view (usually via an observer pattern). Check out INotifyPropertyChanged if using .net
Word of caution: Although I have described how to implement both methods, they should not really be considered interchangeable. There are cases when you want MVC, MVP, and MVVM. I think if you don't have technology limitations around using MVVM, then it is your best choice. I am biased but I think maybe people are moving away from MVC and towards MVVM (or MVP) except for very specific cases like ASP.NET MVC. My article describes this in more detail if you need clarification.
Short summary for when to use each in terms of C#
WinForms -> MVP
WPF -> MVVM
ASP -> MVC (if you can't use ASP.NET
MVC, then MVP will work too)

Categories

Resources