MVC Controllers
MVC Controllers (also called Surface Controllers) are useful if you want to gather form submissions or route requests to certain Externable pages. Surface Controllers are auto-routed meaning that you don't have to add/create your own routes for these controllers to work.
All implementations of Surface Controllers inherit from the base class Umbraco.Web.Mvc.SurfaceController
.
All MVC Surface controllers get routed to:
/umbraco/{areaname}/{controllername}/{action}/{id}
See template explanation below for more details.
Available to everyone (including annonymous requests)
If you want your endpoint to be available for everyone without logging, create MVC controller inheriting from Umbraco.Web.Mvc.SurfaceController
. That will be the case when you want to process custom annonymous forms or redirect user to specific Externable page.
Available to logged in members only
Authorizing a controller for a front-end member is achieved with attribute Umbraco.Web.Mvc.MemberAuthorizeAttribute
You can attribute your controller or action with this attribute which will ensure that a member must be logged in to access the resource. An example:
[MemberAuthorize]
public class AccountController : SurfaceController
{
[HttpPost]
public ActionResult UpdateAccountInfo(AccountInfo accountInfo)
{
// Update the account info for the current member
}
}
There are a few properties that exist for the attribute to give you more control over the authorization process for which members can access the resource:
AllowType
- Comma delimited list of allowed member typesAllowGroup
- Comma delimited list of allowed member groups
Available to logged in users only
Any MVC Controller or Action that is attributed with Umbraco.Web.Mvc.UmbracoAuthorizeAttribute
will authenticate the request for a backoffice user. A base class implementation that already exists with this attribute is: Umbraco.Web.Mvc.UmbracoAuthorizedController
. These MVC controllers are not auto-routed.
Template explained
Our Custom Plugin template contains an example of Surface MVC Controller. See it below explained.
Your plugin name must be unique so that you don't face errors due to conflict with other plugins
Protecting surface controller routes
If you only want a surface controller action to be available when it's used within an Externable form and not from the auto-routed URL, you can add the [ValidateUmbracoFormRouteString]
attribute to the action method. This can be especially useful for plugin based controllers, as this makes sure the actions can only be activated whenever it's used within the website.
namespace TestWebsite.Core.Controllers
{
public class MyController : Umbraco.Web.Mvc.SurfaceController
{
[HttpPost]
[ValidateUmbracoFormRouteString]
public ActionResult HandleSubmit()
{
return RedirectToCurrentUmbracoPage();
}
}
}
Whenever you render an Externable form within your view using Html.BeginUmbracoForm<MyController>(...)
, the forms action will be the URL of the current page (not the auto-routed URL of the surface controller). Externable will therefore add a hidden ufprt
field to the form with an encrypted value containing the controller and action. On form submission, this value is decrypted and Externable will activate the specified action of the surface controller.
@using (Html.BeginUmbracoForm<MyController>("HandleSubmit"))
{
<input type="submit" />
}
This concept is similair to ASP.NET Web Form's view state, but only stores the route information, so the value is considerably smaller. Also note this doesn't protect against Cross-Site Request Forgery (CSRF) attacks: you can use ASP.NET MVC anti-forgery tokens to protect you from this.
Surface controller actions
A surface controller can return a few Externable and Umbraco specific actions.
CurrentUmbracoPage
Returns the current Umbraco page.
namespace TestWebsite.Core.Controllers
{
public class TestSurfaceController : SurfaceController
{
[HttpPost]
public ActionResult PostMethod()
{
if (!ModelState.IsValid)
{
return this.CurrentUmbracoPage();
}
return this.RedirectToCurrentUmbracoPage();
}
}
}
RedirectToCurrentUmbracoPage
Redirects to the currently rendered page.
namespace TestWebsite.Core.Controllers
{
public class TestSurfaceController : SurfaceController
{
[HttpPost]
public ActionResult PostMethod()
{
if (!ModelState.IsValid)
{
return this.CurrentUmbracoPage();
}
return this.RedirectToCurrentUmbracoPage();
}
}
}
This action can also take in a string
value for a querystring parameter in the url or a NameValueCollection
for multiple querystring parameters in the url.
Querystring parameter using a string value
namespace TestWebsite.Core.Controllers
{
public class TestSurfaceController : SurfaceController
{
[HttpPost]
public ActionResult PostMethod()
{
var paramValue = "someValue";
return this.RedirectToCurrentUmbracoPage("param=" + paramValue);
}
}
}
Querystring parameter using a NameValueCollection
namespace TestWebsite.Core.Controllers
{
public class TestSurfaceController : SurfaceController
{
[HttpPost]
public ActionResult PostMethod()
{
var queryStringCollection = new NameValueCollection();
queryStringCollection.Add("param1", "paramvalue1");
queryStringCollection.Add("param2", "paramvalue2");
return this.RedirectToCurrentUmbracoPage(queryStringCollection);
}
}
}
RedirectToCurrentUmbracoUrl
Redirects to the currently rendered url.
namespace TestWebsite.Core.Controllers
{
public class TestSurfaceController : SurfaceController
{
[HttpPost]
public ActionResult PostMethod()
{
return this.RedirectToCurrentUmbracoUrl();
}
}
}
RedirectToUmbracoPage
Redirects to a given page.
namespace TestWebsite.Core.Controllers
{
public class TestSurfaceController : SurfaceController
{
[HttpPost]
public ActionResult PostMethod()
{
//gets the first child page of the current page
var childPage = CurrentPage.FirstChild();
return this.RedirectToUmbracoPage(childPage);
}
}
}
You can also redirect to a page id.
namespace TestWebsite.Core.Controllers
{
public class TestSurfaceController : SurfaceController
{
[HttpPost]
public ActionResult PostMethod()
{
//redirect to a page with id 1054
return this.RedirectToUmbracoPage(1054);
}
}
}
There are overloads for adding a string
querystring parameter or a NameValueCollection
for multiple querystring parameters.