Getting controller name from razor - c#

I seem to be having a difficult getting something that should be easy. From within my view, using Razor, I'd like to get the name of the current controller. For example, if I'm here:
http://www.example.com/MyController/Index
How can I get the controller name, MyController from a Razor expression:
#* Obviously this next line doesn't work
#Controller.Name
*#
I'm new to MVC, so if this is an obvious answer, don't attack me to bad.

#{
var controllerName = this.ViewContext.RouteData.Values["controller"].ToString();
}
OR
#{
var controllerName = HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString();
}

An addendum to Koti Panga's answer: the two examples he provided are not equivalent.
This will return the name of the controller handling the view where this code is executed:
var handlingController = this.ViewContext.RouteData.Values["controller"].ToString();
And this will return the name of the controller requested in the URL:
var requestedController = HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString();
While these will certainly be the same in most cases, there are some cases where you might be inside a partial view belonging to a different controller and want to get the name of the controller "higher-up" in the chain, in which case the second method is required.
For example, imagine you have a partial view responsible for rendering the website's menu links. So for every page in your website, the links are prepared and passed to the view from an action called SiteMenuPartial in LayoutController.
So when you load up /Home/Index, the layout page is retrieved, the SiteMenuPartial method is called by the layout page, and the SiteMenuPartial.cshtml partial view is returned. If, in that partial view, you were to execute the following two lines of code, they would return the values shown:
/* Executes at the top of SiteMenuPartial.cshtml */
#{
// returns "Layout"
string handlingController = this.ViewContext.RouteData.Values["controller"].ToString();
// returns "Home"
string requestedController = HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString();
}

#HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString();
MVC 3
#ViewContext.Controller.ValueProvider.GetValue("controller").RawValue
MVC 4.5 Or MVC 5
#ViewContext.RouteData.Values["controller"].ToString();

To remove need for ToString() call use
#ViewContext.RouteData.GetRequiredString("controller")

Also if you want to get the full controller's name (with "Controller" ending) you can use:
ViewContext.Controller.GetType().Name

I want to add some more information to the previous answers. Maybe someone need.
In order to find Area Name, Controller Name and Action Name in razor view engine you can use:
#{
var areaName = ViewContext.RouteData.Values["area"].ToString();
var controllerName = ViewContext.RouteData.Values["controller"].ToString();
var actionName = ViewContext.RouteData.Values["action"].ToString();
}

#ViewContext.RouteData.Values["controller"].ToString();

Related

How can I pass HTML code stored in a string variable to a view in MVC 5?

I have an action which is defined like this one:
public ActionResult TempOutput(string model)
{
return View((object)model);
}
I also have its view, which is defined like this:
#model String
#{
ViewBag.Title = "TempOutput";
}
<h2>TempOutput</h2>
#Model
And, at one point in my code, I call the action method and the view with this line of code:
return RedirectToAction("TempOutput", "SEO", new { model = tmpOutput });
The point is that, it works all fine when I have a short string, but in my case tmpOutput is a string variable which holds a long HTML code. The thing is that I want to pass that HTML code inside my view, but I don't want it to be displayed as a normal text, but I want it to be parsed as a HTML code and change the view. Currently, when I run the code, I get an error message saying:
The request filtering module is configured to deny a request where the
query string is too long.
How can I solve the problem?
The problem in your case is that redirecttoaction makes a new (302) http request and your 'model' which you are sending will be send with querystring and querystring has a limit then instead try using TempData as:
TempData["mydata"] = tmpOutput ;
and then retrieve TempData value in TempOutput action or directly use it in View as shown.
View :
<div>#Html.Raw(TempData["mydata"])</div>

How to remove the child action in asp.net mvc3

how can i remove the child action in asp.net mvc3. I mean i am having partial views and main views. In the url bar when i entered the child page then it should not load.
for suppose my main page is
localhost:5820/Home/Index
Then when i enter
localhost:5820/Home/Index
then it should work and the child item is
localhost:5820/Home/About
Then when i enter
localhost:5820/Home/About
then it should not open. How can i do that in asp.net mvc. I have several pages like that i have displayed the pages in how can
i rectify this issue
Looks like you are looking for ChildActionOnly attribute:
[ChildActionOnly]
public ActionResult About()
{
return View();
}
It disables direct calls to localhost:5820/Home/About - only rendering as partial view will be available.
UPDATE according to what you need - mark all actions which should return partial views with ChildActionOnly attribute:
public ActionResult Index()
{
return View();
}
[ChildActionOnly]
public ActionResult About()
{
var model = ...
return PartialView("_About", model);
}
And in index view call those actions (from Home controller and other controllers) via:
#Html.Action("About", "Home")
The fact that your ABOUT page is a link inside your HOME page does not mean it is a child action, in fact, from the point of view of MVC they are in the same level, is YOU as a programmer that give the ilussion of hiereachies by providing an order of navigation.
Now, what you can do is:
simply remove the Action Methods from your controller, or
write a simple ignore route like:
routes.IgnoreRoute("YourRuleToIgnoreActions");
this rules should be at the beginning of your RegisterRoutes method in RegisterRoutes to avoid other rules to be triggered
To build up your ignore rules, here is a nice discussion on the topic: http://ardalis.com/IgnoreRoute-in-ASP.NET-Routing-is-Order-Dependent
UPDATE:
Probably too much thinking on this one, but in my opinion, the Models CAN have properties that modify the behaviour of the View, this is because from an architectural point of view, when you are already in the View, your concern is exclusively on the presentation layer, so I think it is perfectly valid to have something like:
public class MyReportsModel{
public bool displaySection1 { get; set;}
//other data
}
and in your views, you can change the presentation in the following way:
#{
if(#Model.displaySection1){
//display as normal
}
}
Of course, when you populate the model you should set that property in each controller according to your needs:
MyReporstModel thisView = new MyReportsModel();
thisView.displaySection1 = true;
// set all properties necessary to display
// if the controller knows that this partial view won't be displayed then
thisView.displaySection1 = false;
But that is no longer a technical issue but an architectural one.
hope it helps,

asp.net mvc routing "view was not found"

very simple basic question
I have only route:
routes.MapRoute(
"Widget", // Route name
"Widget/Frame/{postUrl}", // URL with parameters
new { controller = "Widget", action = "Index", postUrl = UrlParameter.Optional } // Parameter defaults
);
And when i try to open following url:"http://localhost:50250/Widget/Frame/qwerty"
I have an error:
The view 'qwerty' or its master was not found or no view engine
supports the searched locations. The following locations were
searched:
Well...why?
Controller code:
public class WidgetController : Controller
{
//
// GET: /Widget/
public ActionResult Index(string postUrl, int? blogEngineType)
{
return View(postUrl);
}
}
You are returning a View with
return View(postUrl);
Since there is no name of the view (in this overload), the method uses the Action name as view name and looks for it. You probably meant to do
return Redirect(postURL);
I would hazard a guess and say it's because it's actually trying to use the action name of Index(), since that's the default action that you've specified. You're not passing an {action} parameter through the url, so where else will it get the action from?
Can you change your url pattern to Widget/{action}/{postUrl} and see if it works then?
Either that, or set the default value of action to Frame instead. Basically, it has no way of knowing that you're looking for the Frame action, so it fails.
Edit: I see what you're doing now - the action's name is actually Index, right? In that case, I'm not sure, we need to see your controller code. I'll leave the above answer in case it's useful.
Edit 2: You're passing the value "qwerty" as the view name - do you have a view named "qwerty" in the views folder?
If you intend for it to be the model, and for the view name to be "Index", you should call return View((object)postUrl); instead, so that it doesn't get confused.
It's because your return statement is return View(postUrl); and when you pass a string to the View() method it is interpreted as the name of the view to use. So it looks for a view called qwerty since that's what's in that variable. If you want to hand postUrl as a model to the view of your Index action, you'll have to change your return to be return View("Index", postUrl)
Are you sure there is a View called 'qwerty' in the Shared or Widget folder within the Views parent folder?
Otherwise you probably want to use return RedirectToAction(postURL);

Can't find view even though it's there, it's not looking for the correct extension

I'm confused about this one. I'm using razor with MVC 3 and I have a problem with one view on one action.
[HttpGet]
[ActionName("Unsubscribe")]
public ActionResult UnsubscribeGet(string maskedId)
{
return View("Unsubscribe", maskedId);
}
The Unsubscribe.cshtml view is in the correct view folder.
The route is
routes.MapRoute(
"", // Route name
"Unsubscribe/{maskedId}", // URL with parameters
new { controller = "Account", action = "Unsubscribe" });
When going to the following url "/Unsubscribe/db94fddb", the action fires and then the following error is shown when it tries to find the view.
The view 'Unsubscribe' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Account/Unsubscribe.aspx
~/Views/Account/Unsubscribe.ascx
~/Views/Shared/Unsubscribe.aspx
~/Views/Shared/Unsubscribe.ascx
~/Views/Account/db94fddb.master
~/Views/Shared/db94fddb.master
~/Views/Account/db94fddb.cshtml
~/Views/Account/db94fddb.vbhtml
~/Views/Shared/db94fddb.cshtml
~/Views/Shared/db94fddb.vbhtml
Notice it doesn't look for the cshtml extension when looking for Unsubscribe but does when looking for db94fddb
This is only happening with this view, completely at a loss on how to fix it.
** EDIT **
Found it,
I was using System.String as the model. For some reason that was causing it to blow up.
I swapped it to #model UnsubscribeViewModel
[HttpGet]
[ActionName("Unsubscribe")]
public ActionResult UnsubscribeGet(string maskedId)
{
return View("Unsubscribe", new UnsubscribeViewModel { MaskedId = maskedId } );
}
Although this now works I still have no idea why it didn't work before. I have my views set to compile on build so there were no compiler errors.
I would love to know what's happening here.
The overload of the View method you were using takes two strings. It doesn't interpret the second string as a model, it interprets it as the master page name:
protected internal ViewResult View(
string viewName,
string masterName
)
If you instead called it like this, it would work:
return View("Unsubscribe", (object) maskedId);

ASP.NET MVC Routing for Master / Detail Views with "Detail Children"

I have the basic Master / Detail Views working great with the default ASP.NET MVC Route; however I would like to build some URLs like this:
/Class/Details/5 -- General Detail view [Working]
What I'm not sure about (and I'm not tied to this URL format, just something roughly equalivent.)
/Class/5/Details/Logs -- Detail View with Logs
/Class/5/Details/Status -- Detail View with current Status
Another way to put this, is like this:
/{controller}/{id}/{controllerSpecificMaster}/{action}/
What I'm trying to avoid, is cluttering up my Views\Class directory with a bunch of Views, which are all basically derivatives of the Details view.
I'm on ASP.NET MVC 1 and .NET 3.5 SP1.
The first thing you need to get down are your routes. You may have already done this, but in case you haven't, here's a route entry that will handle your custom route needs:
routes.MapRoute("Master_Detail",
"{controller}/{id}/{controllerSpecificMaster}/{action}",
new { controller = "Class",
action = "Index",
id = UrlParameter.Optional,
controllerSpecificMaster = "Details"
});
Then, in your action methods where you want to use the route-specified master page, just include the route key in your method arguments, and then pass it to the view:
public ActionResult Logs(int id, string controllerSpecificMaster)
{
//do something
//return view with master name as argument
return View("Logs", controllerSpecificMaster);
}
If you have to do this a lot, I would suggest creating a custom view engine and override the FindView() method.

Categories

Resources