Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Purpose of public NonAction methods in MVC

i have just started working in MVC and I have one doubt.

Instead of Nonaction method , we can create private method in controller or we can also write method in model and call that from controller.

So , what is the real purpose to use public NonAction method in MVC ?

like image 597
ChandniShah Avatar asked Jul 02 '13 05:07

ChandniShah


People also ask

Why action method must be public?

All the public methods of the Controller class are called Action methods. They are like any other normal methods with the following restrictions: Action method must be public. It cannot be private or protected.

What is public ActionResult in MVC?

An action result is what a controller action returns in response to a browser request. The ASP.NET MVC framework supports several types of action results including: ViewResult - Represents HTML and markup. EmptyResult - Represents no result. RedirectResult - Represents a redirection to a new URL.

Can we write non-action methods in MVC controller?

Marking Public Methods as Non-Action Methods By default, the MVC framework treats all public methods of a controller class as action methods. If your controller class contains a public method and you do not want it to be an action method, you must mark that method with the NonActionAttribute attribute.

Why TempData is used in MVC?

What is TempData and How to Use in MVC? TempData is used to transfer data from the view to the controller, the controller to the view, or from an action method to another action method of the same or a different controller. TempData temporarily saves data and deletes it automatically after a value is recovered.


2 Answers

(I restructured the answer to better address the questions in the comments)

I think, the attribute is here only for better flexibility. As a framework designer, one wants to relax coding constraints off the end user as much as possible. Requirement of not having public non-actions may sound good "in general" but may be too restrictive for some projects. Adding [NonAction] solves their problem (introduced by their bad design though) - and obviously you're not forced to use the attribute, so it's a win-win from a framework designer perspective.

Another reason may be legacy - in the earlier MVC versions only methods marked with [Action] where considered as actions. So when they relaxed the requirement (and all public methods became treated as actions) they kept [NonAction] so that developers won't get too confused.


In general, using NonAction is a bad practice - exactly for the reasons you stated. If something shouldn't be an action, it should not be public in the first place.

Problem with public non-action methods on the controller is that they make people tempted to instantiate your controller and call the method, instead of separating out the common logic:

Compare

public class MyController : IController
{
    public ActionResult Foo(long orderId)
    {
        var order = new OrdersController().GetOrder(orderId); //GetOrder is public
        ...
    }
}

with

public class MyController : IController
{
    public ActionResult Foo(long orderId)
    {
        var order = _orderService.GetOrder(orderId);
        ...
    }
}

The first approach leads to increased coupling between controllers and non-straightforward code in the actions. Code becomes difficult to follow and refactor, and cumbersome to mock/test.

Besides increased coupling, any public non-action method is a security hole - if you forget to mark it with [NonAction] (or, better, change away from public) - because it's treated as normal action and can be invoked externally. I know the original question kinda implies you surely would never forget to attach the attribute if needed, but it's also kinda important to understand what can happen if you would ;) Oh well, and as we're on this, it seems to me that "forgetting the attribute" is more theoretically probable, comparing to "forgetting to make the method private".


Sometimes people say having public non-actions is necessary for unit testing, but again, when something is not an action it most likely can be isolated in a separate class and tested separately. Moreover, even if it's not feasible for whatever reason, marking a method public for testing purposes only is a bad habit - using internal and InternalsVisibleTo is the recommended way.

like image 171
andreister Avatar answered Oct 02 '22 03:10

andreister


This kind of situation may be caused by requirements some testing framework such as you need to do unit testing on that method then you to expose it although its a bad design but can't change these had to bear it out.

By default, the MVC framework treats all public methods of a controller class as action methods. If your controller class contains a public method and you do not want it to be an action method, you must mark that method with the NonActionAttributeattribute.

Real purpose to use public NonAction

To restrict access to non-action method to notify MVC framework that given controller method is not action.

When you try to run a method with NonAction attribute over URL you get the error 404 as response to request.

Ref: http://msdn.microsoft.com/en-us/library/dd410269%28v=vs.90%29.aspx

For Detail: http://weblogs.asp.net/gunnarpeipman/archive/2011/04/09/asp-net-mvc-using-nonactionattribute-to-restrict-access-to-public-methods-of-controller.aspx

like image 20
Satpal Avatar answered Oct 02 '22 02:10

Satpal