MVC 4 Async Controller - asp.net-mvc-4

In MVC 4 i created following async method in controller
public async Task<ActionResult> Test()
{
string str = await TestClient() ;
return View() ;
}
Controller Name : Home
Action Name :Test
When my controller class inherits from "AsyncController" base class then http://localhost/Home/Test dosent work , even debugger is not hit on the action method . But When my controller class inherits from "Controller" base class then it works fine
I am not really sure about the difference it creates based on base class used

AsyncController is the older way of implementing an asynchronous controller; use Controller in all modern code, including async code.

Related

ASP NET Core Define API Controller within class

I'm currently switching from .net framework to .net core 3.1.
Defining Api Controllers inside the namespace is all fine and works.
Now I have the case, that I need to declare the Api Controllers within another class, like this:
namespace Api.Controllers
{
public class MainClass : BaseClass
{
public MainClass()
{
}
[ApiController]
[Route("Test")]
public class TestController : ControllerBase
{
[HttpGet]
public int GetResult()
{
return 0;
}
}
}
}
The result is, that the Api Controller can't be found after calling the "AddControllers" method inside the "ConfigureServices" method of the startup class.
The MainClass is instantiated before the Startup class will be called.
I've tried to change the global route and defining an area like "{area=Test}/{controller=Test}", or set the ApiController attribute above the MainClass, but none of them worked.
Is there a way to get this working?
Looks like the default ControllerFeatureProvider does not treat nested controller types as controller. You can add (don't need to replace) your custom provider to change that behavior, like this:
public class NestedControllerFeatureProvider : ControllerFeatureProvider
{
protected override bool IsController(TypeInfo typeInfo)
{
if(!typeInfo.IsClass) return false;
if(typeInfo.IsAbstract) return false;
var isNestedType = typeInfo.DeclaringType != null;
var isPublic = true;
var parentType = typeInfo.DeclaringType;
while(parentType != null){
isPublic = parentType.IsPublic;
parentType = parentType.DeclaringType; ​
​ }
​ return isNestedType && isPublic; ​
}
}
Then add that provider to the ApplicationPartManager in Startup.ConfigureServices like this:
​​services
.AddMvc()
​​ .ConfigureApplicationPartManager(appPart => {
​​appPart.FeatureProviders.Add(new NestedControllerFeatureProvider());
});
If you want to replace the default ControllerFeatureProvider, just find it in the FeatureProviders and remove it. Of course then you need to ensure that your custom one should handle everything just like what done by the default logic, something like this:
​​//for IsController
return base.IsController(typeInfo) || <...your-custom-logic...>;
NOTE: You can refer to the default implementation of ControllerFeatureProvider to learn some standard logic to implement your own logic correctly. The code above is just a basic example. To me, as long as the classes inherits from ControllerBase and not abstract, they can work fine as a controller to serve requests. There would be no serious troubles except some weird conventions (e.g: class name not ending with Controller is still a controller or some standard attributes applied on the controller class are not working ...).
We should not use nested controller classes. Each controller class should be put in a separate file (as a good practice). However the point of this answer (the most interesting part that I'm pretty sure not many know about, is the use of ControllerFeatureProvider which can help you customize the features set in other scenarios). And really if you really have to stick with your design somehow, you of course have to use this solution, no other way.

Injecting controller in service

Is this doable in ASP.NET Core? I want to move existing HomeContoroller logic to IHomeService, but there're action logic, where they call some base controller methods that are difficult to do without controller, so I thought moving action logic to this service and use DI to get the current controller instance in there. Or maybe there's a better approach?
public class HomeController : ControllerBase
{
public MyController(IHomeService service)
{
}
}
public class HomeService : IHomeService
{
public HomeService(ControllerBase controller, IOtherService otherService)
{
}
}
There are two problems with your approach:
HomeService accepts a ControllerBase instance. Since all controller classes inherit from ControllerBase. While you could map a specific type to ControllerBase in your DI system, this would not be very useful.
You are introducing a chicken or the egg problem with the circular dependency on ControllerBase:
HomeController depends on HomeService and
HomeService depends on having a controller (most probably HomeController)
To break the cycle you could remove controller from the constructor of HomeService and pass it as parameter to those methods of IHomeService that need access controller.
Another approach would be to change controller to a property and wire up instances in the constructor:
public class HomeController
{
public HomeController(IHomeService homeService)
{
// Assign controller to service here:
homeService.Controller = this;
}
}
I would recommend to use the method parameter approach, so the compiler forces you to pass controller where it is needed.

Unable to call web api when constructor have parameter

I have create a web api controller, I have repository pattern so i used Ninject. In constructor i creating Object for interface. Its working fine when i am using it in Normal Controller class. But when i create same in api controller constructor it not working.
Code:
//Its not working
IAdminRepository mAdminRepository;
public AccountApiController(IAdminRepository pAdminRepository)
{
mAdminRepository = pAdminRepository;
}
[HttpPost]
[ActionName("ValidateLogin")]
public LoginResponse ValidateLogin([FromBody] LoginInfo login)
{
// some code hare
}
//But its working
private AccountApiController()
{
}
Its working as its have no parameter in constructor. Once again telling u that i have used same parameterized constructor in Normal controller classes in same project that's working.

What controller Initialize function does ASP.Net MVC4

i am new in MVC and learning. here i am putting some code. so see first
public class HomeController : BaseController
{
private IProductRepository productRepository;
private string strRouteValue;
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
base.Initialize(requestContext);
strRouteValue = this.ControllerContext.RouteData.Values["method"].ToString();
this.productRepository = Factory.Create(strRouteValue);
}
[HttpGet]
public ActionResult Index(int id)
{
productRepository.Get(id);
return View();
}
[HttpPost]
public ActionResult Index(Product model)
{
productRepository.Add(model);
return View();
}
}
what Initialize function does ?
every one must say this is where people would init many object, if so then we can do it in constructor of controller too. so what is special about controller Initialize function ?
what is difference between controller Initialize function and controller constructor ?
Check the documentation for that method: MSDN: Controller.Initialize():
Initializes data that might not be available when the constructor is called.
This method cannot be called directly. Override this method in order to provide additional processing tasks before any ActionResult methods are called, such as setting the thread culture or assigning a custom provider for TempData objects. If you override this method, call the base control's Initialize method.
And as I suggested on your previous twenty or so questions about MVC, Dependency Injection and controller instantiation: stop piecing together advice from poor blogposts and irrelevant answers on SO. Buy a decent MVC book and read it from cover to cover. Then do the same with a book about Unit Testing. You will never get a thorough understanding of things if you continue this way.
There is a difference between instantiating a controller and initializing it. Instantiating is moreover a .NET concept not MVC, so every class is automatically instantiated using default constructor. So, constructor is basically a concept of class whereas Initializing is concept of action method. We override Initialize() method in order to provide additional processing tasks before any ActionResult methods are called, such as setting the thread culture or assigning TempData objects etc....

Phalcon Initialize() is not working

I have 2 Controllers, TEST1Controller and TEST2Controller
In TEST2Controller I have a initialize() function setting value of a property.
If I try to access TEST2Controller directly from the browser, everything works perfectly.
But when I call a TEST2Controller method from TEST1Controller, it seems that initialize() function is not being called in TEST2Controller.
TEST1Controller:
namespace Modcont\Controller;
use Modcont\Controller\Test2Controller;
class Test1Controller extends BaseController
{
function gettestAction()
{
$t = new Test2Controller(); // calling TEST2 Controller Method Within TEST1 Controller
echo $t->dotestAction(" MYAPP ");
}
}
TEST2Controller:
namespace Modcont\Controller;
class Test2Controller extends BaseController
{
public $prefix;
function initialize()
{
$this->prefix = 'your name is';
}
function dotestAction($name)
{
return $this->prefix.' : '.$name;
}
}
Phalcon offers two ways for controller initialization, thy are the initialize and onContruct methods. The basic difference between these two methods is that initialize is called only when a controller is created by the framework to proceed with the execution of an action. Since you instantiating a controller object ad-hoc, initialize will not be called, only onConstruct will. So you'll need to put your initialization logic there:
function onConstruct()
{
$this->prefix = 'your name is';
}
Also, implementing native constructors in controller is discouraged, but if you do so, make sure to call the parent constructor in your own constructor: parent::__construct();.
All this information can be found in the Docs.