I have a View - _Edit which lives in News M/V/C.
I reuse the V/M via the CategoryController as:
return PartialView("/Views/News/_Edit.cshtml", model);
How from within the View - _Edit can I alert the controller name?
When I:
alert('#ViewContext. RouteData.Values["controller"].ToString()');
The Value is: News
However, the URL is: /Category/foobar
Is there a way to get the value 'Category' to alert? thanks
I have put this in my partial view:
#HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString()
in the same kind of situation you describe, and it shows the controller described in the URL (Category for you, Product for me), instead of the actual location of the partial view.
So use this alert instead:
alert('#HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString()');
I do it like this:
#ViewContext.RouteData.Values["controller"]
Create base class for all controllers and put here name attribute:
public abstract class MyBaseController : Controller
{
public abstract string Name { get; }
}
In view
#{
var controller = ViewContext.Controller as MyBaseController;
if (controller != null)
{
#controller.Name
}
}
Controller example
public class SampleController: MyBaseController
{
public override string Name { get { return "Sample"; }
}
Other way to get current Controller name in View
#ViewContext.Controller.ValueProvider.GetValue("controller").RawValue
Just use:
ViewContext.Controller.GetType().Name
This will give you the whole Controller's Name
You are still in the context of your CategoryController even though you're loading a PartialView from your Views/News folder.
You can use any of the below code to get the controller name
#HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString();
If you are using MVC 3 you can use
#ViewContext.Controller.ValueProvider.GetValue("controller").RawValue
For anyone looking for this nowadays (latest versions) of ASP.NET Core MVC, you can use:
#Context.Request.RouteValues["controller"].ToString()
Related
How would I go about creating a custom module that has a controller with an action name that is dynamic, in the sense that it can be configured by the user in the admin area at will and be automatically updated in the custom module?
You can override this method in your controller:
public function getActionMethodName($action)
{
return 'indexAction';
}
public function indexAction()
{
//action name
var_dump($this->getRequest()->getActionName());
}
Then always will go to the index action, where you can use the original action name as a parameter.
then:
http://mysite/mymodule/mycontroller/im-dracula-blablabla
Will work!
I think you can approach this by using magic php method __call on your controller.
I assumed that you store your action name in a Magento config named 'mymodule/controller/action', so you can get the value using :
Mage::getStoreConfig('mymodule/controller/action');
Then you have the controller for example Mymodule/controllers/TestController.php
And you add the method in that controller like this :
public function __call($method, $arg) {
if ($method == Mage::getStoreConfig('mymodule/controller/action')) {
//Do whatever you want
}
}
This will make your controller //Do whatever you want when you accessing it using the action you specified in the config. The basic idea is like that. Hope this helps.
I have a Controller with syntax like this:
public class CrudController<TEntity> : Controller
Now if I need a CrudController for Entity User, I just need to extend the CrudController like this
UserCrudController : CrudController<User>
Its working just fine. But, the thing is, the UserCrudController is simply empty. Also, there are some other CrudControllers which are empty too.
Now, I am looking for a way to avoid writing the empty crud controllers. I simply want to create Instances of CrudController with appropriate generic argument. Perhaps by a strict naming convention as described bellow.
The URL will be like: #Html.ActionLink("Create", "UserCrud")
When the URL will be received, it will try to locate the controller named UserCrud (The default thing)
If it fails to locate UserCrud, Crud<User> will be created.
Now, I can do the things I want to do. But exactly where do I do these? Where is the url parsed in mvc?
With help of Craig Stuntz's comment on the question and this question and its accepted answer, I have solved my problem.
I have implemented a custom CotrollerFactory
public class CrudControllerFactory : DefaultControllerFactory {
protected override Type GetControllerType(System.Web.Routing.RequestContext requestContext, string controllerName) {
Type controllerType = base.GetControllerType(requestContext, controllerName);
if(controllerType == null) {
int indexOfEntityEnd = controllerName.LastIndexOf("Crud");
if(indexOfEntityEnd >= 0) {
string entityName = controllerName.Substring(0, controllerName.Length - indexOfEntityEnd - 1);
// Get type of the CrudController and set to controller tye
}
}
return controllerType;
}
}
And then in Application_Start(), I added this line:
ControllerBuilder.Current.SetControllerFactory(typeof(CrudControllerFactory));
I'm using ViewBag.Message with the same message several times into the methods on the controller.
It is possible to declare ViewBag.Message on the top of the class, so can be used in the whole controller without repeat the code?
Assuming Razor syntax you can achieve this with.
#{string pageMessage = ViewBag.Message.ToString();}
then pageMessage is a local variable available to the page, for example:
<h1>#pageMessage</h1>
EDIT
ViewBag is a dynamic object which is a member of the Controller base class so to just specify this once in the whole controller you could put something in your controller constructor.
public class MyController : Controller
{
public MyController()
{
ViewBag.ViewTime = DateTime.Now.ToString();
}
// rest of controller code
}
I know how to get the current controller name
HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString();
But is there any way to get the current controller instance in some class (not in an action and not in a view)?
By default you can only access the current Controller inside a controller with ControllerContext.Controller or inside a view with ViewContext.Context. To access it from some class you need to implement a custom ControllerFactory which stores the controller instance somewhere and retrieve it from there. E.g in the Request.Items:
public class MyControllerFactory : DefaultControllerFactory
{
public override IController CreateController(RequestContext requestContext, string controllerName)
{
var controller = base.CreateController(requestContext, controllerName);
HttpContext.Current.Items["controllerInstance"] = controller;
return controller;
}
}
Then you register it in your Application_Start:
ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());
And you can get the controller instance later:
public class SomeClass
{
public SomeClass()
{
var controller = (IController)HttpContext.Current.Items["controllerInstance"];
}
}
But I would find some another way to pass the controller instance to my class instead of this "hacky" workaround.
Someone will have to correct me if what I am doing is detrimental to the whole Asp.Net page life cycle / whatever but surely you can do this:
In controller
ViewBag.CurrentController = this;
In view
var c = ViewBag.CurrentController;
var m1 = BaseController.RenderViewToString(c, "~/Views/Test/_Partial.cshtml", null);
In my case, I had a base controller that all controllers extend. In that base controller lived a static method called RenderViewToString and it required a controller. Since I figured I could just instantiate a new instance of an empty controller at this point for c, I just sent it to the view in the lovely ViewBag container that exists in the world of Asp.Net MVC. For reasons I could not go into now, I could not retrieve the string in the controller and send just that back to the view (this was what I had done earlier before requirements changed).
The reason I have done it this way is in other languages like PHP and JS, there are similar simple ways to transfer classes around.
With the Razor view engine in MVC3,
Is it possible to render a legacy ascx?
I was expecting to be able to do something like:
#Html.RenderPartial("Footer.ascx")
Yes. Try this instead:
#Html.Partial("Footer")
or
#{ Html.RenderPartial("Footer"); }
Just wanted to add that I haven't seen a lot of people posting this solution:
Html.RenderAction("Footer", "Home");
This is better practise if you are using MVC, because you can specify any data you need in the controller instead of trying to manage it in a free-floating partial view. Very beneficial if you use a BaseController class to initialize all your calls.
public class HomeController : Controller {
// ...
[ChildActionOnly]
public PartialViewResult Footer() {
// do work
return PartialView();
}
// ...
}