In asp.net mvc 2 : how to access http post data inside constructor of any controller - asp.net-mvc-2

My controller has abstract base controller. I want to access the form post data inside abstract base class constructor. How can we do that ?
public abstract class AppController : Controller
{
public AppController()
{
// request post data required here
}
}
public class ProductController : AppController
{
public ProductController() { }
}
Purpose : Updating second dropdown on change of first dropdown. Both are on MASTER page.
Code given above is one of the 2 options to pass data to master page:
Add using ViewData in ALL the action methods.
Do it in only one place using abstract base controller - add the required data using ViewData inside its constructor and make our main controller class implement this abstract base controller class. So that we don't have to add the viewdata for master page in all action methods.

I don't know what is your final goal with this but this is something which is not recommended to be done in MVC. The Request object is not yet initialized in the constructor of the controller. You could try to use the native HttpContext object:
string foo = System.Web.HttpContext.Current.Request["foo"];
but that's something extremely bad and I would never recommend you doing this as now your controller is coupled to the static native HttpContext instance without any chance of unit testing it.
Instead of using the constructor you could override the Initialize method of your controller where you will have access to the request context and you could read posted data:
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
{
base.Initialize(requestContext);
string foo = requestContext.HttpContext.Request["foo"];
}

Related

Symfony2 get public services in controller

Much ink has flowed about Sf2 controller/container. I face with follow situation:
app/console container:debug security
...
> 4
[container] Information for service security.token_storage
Service Id security.token_interface
Class Symfony\Component\Security\Core\Authentication\Token ...
...
Public yes
LoginBundle\DefaultController.php
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller
{
public function indexAction()
{
dump(Controller::get('security.token_storage'));
...
works OK, obviously.
LoginBundle\UserUtilsController
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class UserUtilsController extends Controller
{
public function getRoleById()
{
dump(Controller::get('security.token_storage'));
...
throw: Error: Call to a member function get() on a non-object
In Sf2 Book - Service container I found:
In this example, the controller extends Symfony's base Controller, which gives you access to the service container itself. You can then use the get method to locate and retrieve the my_mailer service from the service container.
The misunderstanding is:
- Both controllers extends basic controller which itself extends ContainerAware which implements ContainerAwareInterface which set container.
- Both controllers access same public service container.
So, why the second controller it doesn't work?
I know that the question is old but I don't want to inject a controller as service and I think it is redundant and wrong to redeclare a public service in services.yml
Thank you in advance.
I found the answer myself and I want to share for every one is in same situation...
The UserUtilsController doesn't work because it's not working in this manner. The Symfony architecture is interesting if you get to know it.
LoginBundle\Controller\UserUtilsController
// For this job we don't need to extends any class..
class UserUtilsController
{
// but we need a property for injecting the service in it
private $token;
// Now let's inject service into our property $token
public function __construct($token)
{
$this->token = $token;
}
// It's not done but let pretend it is and let's use it
public function getRoleById()
{
...
return $this->token->getToken()->getRoles();
...
services.yml
#here it's the magic
services:
# this is a new services container
user.loggeduser_utils:
# this is my class (second class)
class: LoginBundle\Controller\UserUtilsController
# this is how I feed my _construct argument
arguments: ["#security.token_storage"]
So I just inject an existing service in my new class.
Now, to use this we must to call in first class:
LoginBundle\Controller\DefaultController.php
class DefaultController extends Controller
{
public function indexAction()
{
// because my class is now a service container we call in this way
$userRoleId = $this->get('user.loggeduser_utils');
...
This solution above is almost trivial simple AFTER understanding the Sf2 DI model.

Web Api 2 Inheritance No route providing a controller name was found to match request URI

Basically I cannot get my Web Api 2 application to work.
First of all here are my requirements.
In my application I am creating a dozen of controllers ( ProductController, ItemController, SalesController...etc). There are 2 actions which are absolutely common in all my controllers:
FetchData, PostData
(Each controller then may implement a number of other methods which are sepcific to its business domain )
Instead of repeating these actions in every controllers like:
public class ProductController:ApiController{
[HttpPost]
public MyReturnJson FetchData( MyJsonInput Input){
....
return myJsonResult;
}
}
public class SalesController:ApiController{
[HttpPost]
public MyReturnJson FetchData( MyJsonInput Input){
....
return myJsonResult;
}
}
I decided to create a base controller MyBaseController:
public class MyBaseController : ApiController{
[HttpPost]
public MyReturnJson FetchData( MyJsonInput Input){
....
return myJsonResult;
}
}
with the 2 methods so every other controller would inherit them (It saves me from repeating them in every controller). The common base class has been defined and implemented in a separate assembly which is then referenced in my web project.
Then in my javascript client (using breeze) I call a specific controller like
breeze.EntityQuery.from('FetchData')
where my serviceName is 'my_api/product/'
(in the WebApiConfig, the routing table has been defined like:
config.Routes.MapHttpRoute(
name: "my_api",
routeTemplate: "my_api/{controller}/{action}"
);
But when the javascript code is executed I get the error message:
No route providing a controller name was found to match request URI
http://localhost:xxxxx/my_api/product/FetchData
If I don't use a common base class but instead repeat this method (FetchData) in every class (basically ProductController inherits directly from ApiController and not from MyBaseController) every thing works fine and my method is hit. I thing there is a problem with the inheritance scheme. Maybe there is something I don't get (first time using Web Api 2) or some constraints (routing, configuration...) I do not respect. Right now I am stuck and I would appreciate any suggestion which might point me to the right direction. Is inheritance allowed in Web Api 2?
I am not sure why your code is not working. But in the next link (http://www.asp.net/web-api/overview/releases/whats-new-in-aspnet-web-api-22#ARI) you can see an example of inheritance using attribute routing.
This is the code example:
public class BaseController : ApiController
{
[Route("{id:int}")]
public string Get(int id)
{
return "Success:" + id;
}
}
[RoutePrefix("api/values")]
public class ValuesController : BaseController
{
}
config.MapHttpAttributeRoutes(new CustomDirectRouteProvider());
public class CustomDirectRouteProvider : DefaultDirectRouteProvider
{
protected override IReadOnlyList<IDirectRouteFactory>
GetActionRouteFactories(HttpActionDescriptor actionDescriptor)
{
return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>
(inherit: true);
}
}
I hope that it helps.

MVC Model Binding with Attribute Routing

Converting an MVC 3 app to MVC 5 and relying exclusively on Attribute Routing. All is good but I am unable to define a route for a controller method that accepts a (not so) complex object as a parameter.
If I omit the parameter in the route, my controller/method is never invoked and I receive a 404 (as I would expect). When I include the viewModel parameter as part of the route, my method is invoked but the parameter is always null.
This code worked fined before with "classic" routing and no specific route was needed to model bind my viewModel parameter. I never defined it as part of any route other than including the controller and method names. The view is unchanged.
[RoutePrefix("Text")]
[Route("{action}")]
public class TextController : Controller
{
[HttpGet]
[Route("{jobTextID}")]
public ViewResult Edit(Guid jobTextID)
{
// this (get) works fine
}
[HttpPost]
[Route("{viewModel}"]
public RedirectToRouteResult Edit(TextEditViewModel viewModel)
{
// viewModel is always null
}
}
I think you should add the id to the POST action:
[HttpPost]
[Route("{jobTextID}")]
public RedirectToRouteResult Edit(Guid jobTextID, TextEditViewModel viewModel) { }
The resource is identified by the URL, not by a parameter in the body of the request. Use jobTextID to retrieve the entity from the database and ignore the id from the viewModel.

ZendFramework Send variables from Controller to View (Best pactice)

I have been working in Zend Framework for a while and I am currently refactoring some parts of my code. One of the big thing I would like to eliminate is my abstract controller class which initiate a lot of variables which must be present in all my controller such as $success, $warning and $error. This part can be done in controller pluggins but what would be the best way to send these variables to the related view. Currently I am using a custom method in my abstract controller class which i call from within all my controllers.
protected function sendViewData(){
$this->view->success = $this->success;
$this->view->warning = $this->warning;
$this->view->error = $this->error;
}
which is then called in all the actions of all of my controllers throught
parent::sendViewData();
I was looking to automate this process through a plugin controller or anything better suited for this
You could set a postDisplatch method in your abstract controller to initialize the view data (See section "Pre- and Post-Dispatch Hooks").
That way, in each actions, you could initialize your $this->success, $this->warnning or $this->error variables, and it would be pass to the view after the action is executed.
The Best pactice is, define a base controller and let other controllers to extend this, instead of directly calling the Zend_Controller_Action method
// Your base controller file ApplicationController.php
class ApplicationController extends Zend_Controller_Action {
// method & variable here are available in all controllers
public function preDispatch() {
$this->view->success = $this->success;
$this->view->warning = $this->warning;
$this->view->error = $this->error;
}
}
Your other normal controllers would be like this
// IndexController.php
class IndexController extends ApplicationController {
}
Now these (success, warning & error) variable are available in all views/layout files, In ApplicationController.php you can also hold shared functionality of other controllers.

how to parametrize an import in a View?

I am looking for some help and I hope that some good soul out there will be able to give me a hint :)
I am building a new application by using MVVM Light. In this application, when a View is created, it instantiates the corresponding ViewModel by using the MEF import.
Here is some code:
public partial class ContractEditorView : Window
{
public ContractEditorView ()
{
InitializeComponent();
CompositionInitializer.SatisfyImports(this);
}
[Import(ViewModelTypes.ContractEditorViewModel)]
public object ViewModel
{
set
{
DataContext = value;
}
}
}
And here is the export for the ViewModel:
[PartCreationPolicy(CreationPolicy.NonShared)]
[Export(ViewModelTypes.ContractEditorViewModel)]
public class ContractEditorViewModel: ViewModelBase
{
public ContractEditorViewModel()
{
_contract = new Models.Contract();
}
}
Now, this works if I want to open a new window in order to create a new contract... or in other words, it is perfect if I don't need to pass the ID of an existing contract.
However let's suppose I want to use the same View in order to edit an existing contract. In this case I would add a new constructor to the same View, which accepts either a model ID or a model object.
"Unfortunately" the ViewModel is created always in the same way:
[Import(ViewModelTypes.ContractEditorViewModel)]
public object ViewModel
{
set
{
DataContext = value;
}
}
As far as I know, this invokes the standard/no-parameters constructor of the corresponding ViewModel at composition-time.
So what I would like to know is how to differentiate this behavior? How can I call a specific constructor during composition time? Or how can I pass some parameters during the Import?
I really apologize if this question sounds silly, but I have only recently started to use MEF!
Thanks in advance,
Cheers,
Gianluca.
You CAN do this. Check out the Messenger implementation in MVVM-Light. You can pass a NotificationMessage(Of Integer) to send the right ID to the view model. The view model has to register for that type of message, and load it when a message is sent.
MEF Imports by default only have a parameterless constructor.