How do I get the Area (or the path) of where a View is being scaffolded? - t4

PROBLEM:
I am customizing the MVC 5 templates for scaffolding views.
I need to be able to get the area name for the area where the view is being created.
EG, I want to get be able to set the value for the variable areaName for the Url Action params:
Url.Action("Index", "<#= ViewDataTypeShortName#>s", new { area = "<#= areaName #>", page<#= ViewDataTypeShortName#>s = x }), ViewContext, NormalizePath("~/Areas/<#= areaName #>/Views/<#= ViewDataTypeShortName#>s/"))
In a controller, I can do:
<#
var areaName = GeneratedTextTransformation.AreaName;
#>
But in the View T4 template this is not available.
So how would I get the name of the area where I am creating the view?
EDIT:
Because MVC uses convention over configuration, I could get the area if I had a way to get the path of the View file that is being created (as in:
/Areas/[Area Name]/Views/
So the question reduces to:
QUESTION:
How do I get the path of where a View is being created by the T4 ASP.NET MVC scaffolding?

I have solved this by using the AreaName property (available in T4 template for controller) in ViewBag.AreaName and reading this in the view.
NOT pretty, but it will work.
However, I would much sooner know how to access the Area the files are being created in in my T4 code. See the edit to my question.

Related

How to render a ShapeTemplate without a contentitem?

im new to orchard and my brain is burning because of the MVCSHD model
(Model View Controller Shape Handler Driver)
From Orchard docu:
Shapes are dynamic data models that use shape templates to make the data visible to the user in the way you want. Shape templates are fragments of markup for rendering shapes. Examples of shapes include menus, menu items, content items, documents, and messages.
I would like to display a Shape Template and provide a Model into the view that is not a ContentPart and got no ContentItem.
Because i want to create this Model in the Controller (or in the driver later if i get this working finally).
The content of the model is dynamicly created.
in the Controller this is not working:
TestThingie testThingie = new TestThingie (5);
_orchardServices.ContentManager.BuildDisplay(testThingie,"Summary");
Because testTingie does not have a contentItem...
Is there any other way to display a shapeTemplate with a Model? What am i missing here?
Is it just me or is it kinda impossible to gain furhter Information about how all this stuff is about to work out of the Documentation?
The BuildDisplay method is for crafting the display shapes of a given content item. You don't have a content item, so you cannot use that method.
What you can do however is use the dynamic Display:
public ActionResult MyAction() {
TestThingie testThingie = new TestThingie(5);
return View(myShape);
}
Then in your Views/MyControllerName/MyAction.cshtml:
#Display.MyShape(Thingie: Model.TestThingie)
And in your MyShape.cshtml:
#{
TestThingie thingie = Model.Thingie;
}

Alternative for ViewData and QueryString

I have a page(a.aspx) to which im navigating from two different pages(ie there is a link in these two pages where it navigates to a.aspx)
to differentiate from which page i was navigated to a.aspx i used the below code.
passed Querystrings(B1,B2) to the target page as below
Html.ActionLink("test" "Testing", new { Controller = "Stats",prev="B1"},new { #class = "link",target="_self" })
Html.ActionLink("test" "Testing", new { Controller = "Stats",prev="B2"},new { #class = "link",target="_self" })
and in the action of the target page controller i used the below code
ViewData["prev"] = Request.QueryString["prev"].ToString();
and im using this ViewData in the target page ie a.aspx.This is working fine..
Im abit reluctant to use Query.string and ViewData for the above requirement.Please suggest any other alternative approach for the same.
You can use this,
Get the name of the controller
#ViewContext.Controller.ValueProvider.GetValue("controller").RawValue
Get the name of the action
#ViewContext.Controller.ValueProvider.GetValue("action").RawValue
I found that here.
Why not navigate to two separate actions that return the same view? Then, return a model to the view that will indicate the "from" page. You'll know which page you came from by virtue of which action gets hit. It's cleaner, far less complicated, and easier to maintain than trying to pass around this sort of thing in a querystring, viewdata, viewbag, etc. That being said, if you are having to do a lot of this sort of thing, creating separate actions each time around is not reali

MVC 3 Routing to an Area

How does one Route from one Area to another?
In the default project, there are no area's, but once you add an Area, how could I redirect from the default Home page to a page inside my new Area?
I don't see a RedirectTo* method which takes a parameter for an Area name anywhere.
Unless I'm missing the point of Area's completely?
Inside our views, we don’t need to specify the area route data value when generating
links to other controller actions inside that area. We only supply the action name, because the controller and area name will come from the existing route data for the current request. If we want to link to an outside area, we’ll need to supply that route data explicitly.
return RedirectToAction("yourAction", "YourController", new { area = "yourArea" });
The "area" route value needs to match the AreaName used in the AreaRegistration class for the URL to generate correctly.
This code in your view will link you to the Admin area, regardless of which area you are currently in:
#Html.ActionLink("Click Me", "ActionName","ControllerName",new { Area = "AreaName"}, null )
e.g. (poor made up example)
#Html.ActionLink("Administer User", "Home","UserAdmin",new { Area = "Admin"}, null )
The final null in the call corresponds to HtmlAttributes, and I usually leave it as null.

How can I have a template "view" in CodeIgniter 2.0?

I guess it's a view within a view, but I'd rather it happen automatically. Any help?
Templates, or layouts as they are often called in various MVC frameworks, can be achieved a number of ways in CodeIgniter, but ultimately in any case, you're placing views within views (although it's bad practice to call a view directly from within another view).
One way to achieve this would be to load your internal views into an array, then pass that array into your layout view:
// Get ID From Segment
$id = $this->uri->segment(2);
// Get Article Data
$this->load->model('article');
$article = $this->article->getArticle($id);
// Define Layout View(s)
$layout['title'] = $article->title;
$layout['keywords'] = $article->keywords;
$layout['description'] = $article->description;
$layout['content'] = $this->load->view('articles/detail',array(
'body' => $article->body;
),true);
// Render Layout
$this->load->view('layouts/default',$layout);

How do you handle displaying navigation and sub navigation in an MVC app?

I'm having trouble determining where to place navigation for an MVC app. For example, say you have the following structure:
Conferences
South Eastern Conference
Florida Gators
Georgia Bulldogs
Arkansas Razorbacks
Pac-10
USC
Hawaii
Big East etc...
How would you best create a structure for implementing a 'main' navigation and subsequent 'sub' navigation? Using the hypothetical example, You'd have specific sub navigation for each conference, showing its respective colleges (and only that conferences colleges).
Is this something you'd handle in the main view and just hide the non-selected conference?
Or would you create a menu helper (or yet another partial) and call that from each individual college's view?
Best way is to use multiple, nested master pages. e.g. Site.master would contain your top-level nav (list of conferences?) then you'd have a different master page for each conference that would 'extend' site.master. You can, in theory, have as many nested master pages as you want. Finally, Florida Gators etc would be 'real' views (i.e. non-master pages).
The tricky part is telling any parent master page which navigation item is currently selected. Because you can't bind master pages to the ViewModel you'll have to use the View Dictionary e.g. View["SelectedMainNavItem"].
Why not use some global layout template that always displays the main navigation, and relies on some helper to render the subnav? (The helper may be superfluous -- you might just output the subnavigation inline in the layout template)
Your controller passes current category/sub-category, and some data structure describing the current subnavigation options, to the view.
After contemplating this issue for a while along with the suggestions, I came up with this solution. Since my subnavigation will always be below the main navigation, I decided to go with the Convention over Configuration method.
In my Site.Master, I have the following two render partials. One displays the main navigation and the other makes a call to BuildSubNavigation to display get the name of a partial to render:
<% Html.RenderPartial("_MainNavigation"); %>
<% var submenu = ViewContext.BuildSubNavigation();
if (submenu != null) {
Html.RenderPartial(submenu);
}%>
Granted, this could be thrown into a Helper, and I intend to do that, this is more explicit and aids in the understanding of the issue.
What this does is call the BuildSubNavigation method. It goes with the convention that if a controller is to have a specific sub navigation, there will be a partial in the form of "_Navigation" So in the spirit of the example, one partial would be "_SouthEasternConferenceNavigation" What I do is then check to see if the current view actually exists. If it does, I return the name, where it's then used to render the partial.
public static string BuildSubNavigation(this ViewContext vc) {
var controller = vc.RouteData.Values["controller"] ?? "";
var viewName = "_" + controller + "Navigation";
if (ViewExists(vc.Controller.ControllerContext, viewName, null)) {
return viewName;
} else {
return null;
}
}
And this is the method that checks whether the View actually exists against the current View Engine:
public static bool ViewExists(ControllerContext cc, string viewName, string masterName) {
if (ViewEngines.Engines.FindView(cc, viewName, masterName).View != null) {
return true;
} else { return false; }
}
I'm unsure if this is the best way to do this, but it's working rather well for a small project I'm currently working on.
Thanks for the answers!

Resources