CleintDependency path with no Layout specified - asp.net-mvc-3

I have an ASP.NET MVC 3 site that makes use of a ClientDependency framework for dep. resolution (CSS/JS).
My base path's are defined in /Shared/_Layout.cshtml like this:
#MvcHtmlString.Create(Html.RenderCssHere(new List<IClientDependencyPath> {
new BasicPath("Base", "~/Content/themes/base"),
new BasicPath("Content", "~/Content")
}))
I want to have one page without a standard layout. I force it by calling
#{
Layout = null;
Html.RequiresCss("FileUpload/fileUpload.css", "Content", 20);
}
However, I can no longer request a dep. like shown above, since "Content" path isn't defined.
I am rather new to ClientDependency framework, so which is the best way for me to get my dependencies in a non-layout view?

I need to have the Path declared somewhere in the View, as well as the RenderCss/JsHere element, so if I don't use a shared layout, I had to re-declare it in my custom page all together.

Related

set priority to script and css in asp.net mvc 3

I have built the tree view using third party javascript plugins. I have also use the web templates for my asp.net MVC 3 application. And use Layout view linking to lot of css and javascript.In my category view I want to display the tree view. But the due to script of layout view the tree view is interrupted and not displaying properly. When I put Layout = Null, it shows properly. How can I set priority to the link of script and css link for displaying tree view properly
Take a look at ClientDependancyMvc NuGet package.
It allows to set priority to clientside resources like this:
Html.RequiresCss("Bootstrap/bootstrap.min.css", "Content", 2);
Html.RequiresCss("Bootstrap/bootstrap-responsive.min.css", "Content", 3);
Html.RequiresJs("jquery/1.7.1/jquery.min.js", "googleCDN", 1);
Html.RequiresJs("jqueryui/1.8.18/jquery-ui.min.js", "googleCDN", 2);
Where the last parameter is priority of inserting element into page. More info here.

Change layout in controller depending on url

I have controller PlayerController and actions inside: View, Info, List.
So on urls "/Player/View" i get result with default Layout.
I want to get result with different Layout on request "/External/View".
How can i achieve this?
Although you can override the layout from the controller as has been suggested in another answer, in my opinion this means the controllers are getting just too involved in determining what the UI will be. Best to leave this purely to the Views to decide.
The closest to what you're asking is to do this in your current "~/Views/_ViewStart.cshtml":
#{
if(Context.Request.Path.StartsWith("/External", StringComparison.OrdinalIgnoreCase))
Layout = "~/Views/_ExternalLayout.cshtml";
else
Layout = "~/Views/_Layout.cshtml";
}
Where "~/Views/_ExternalLayout.cshtml" is your alternative layout.
Might want to check the leading "/" is correct on there, I can't remember if it is.
If you put this in the existing _ViewStart, then any view that is being rendering in response to a url starting with "/External" will use this new layout, otherwise the 'normal' one will be used.
Another approach is to use the routing table to add a route value that can be used here to make a layout decision; but I've gone for this approach to keep it simple.
You can specify which layout should be used when returning a view inside your 'ExternalController' controller action.
return View("View", "~/Views/Shared/_AnotherLayout.cshtml")

Can I prevent a shared layout for being used for error messages?

I'm using a shared layout file, set up in _ViewStart.cshtml, for most of my site. Something along the lines of:
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
There is little to no information shared between most of my site, and the error reporting pages. How do I distinguish between the two situations?
I would like the shared layout to be loaded for all pages, except any error reporting ones.
you can change the layout on a per page/view basis
#{
var model = ViewContext.Controller.ViewData.Model;
if (model is System.Web.Mvc.HandleErrorInfo) {
Layout = "";
} else {
Layout = "~/Views/Shared/_Layout.cshtml";
}
}
This is from my Post.vbhtml page - i just need to change the Layout page to use a different layout.
For completion, this question has a a popular, sometimes incorrect solution provided below. Choose with care, use accepted answer if unsure.
There are subtle and sometimes important differences between the accepted answer and the popular alternative below. The alternative below leads to a result which looks right most of the time, but doesn't always work. This appears to be due to the load order and execution of view files - the topmost shared view is loaded and executed first. If that first load + execute process has side effects, this solution will break in strange and important ways.
_ViewStart.cshtml
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
Instruct the appropriate views not to use a Layout, by adding the following to the top of the view files:
ErrorView.cshtml
#{
Layout = "";
}

Inject selected view path as HTML comment to start and end of action's output

I'm currently putting together a multi-tenancy web app using MVC 3. At least 30 different Web sites will share a common codebase, and while also sharing similar under-the-hood functionality, they are need to look significantly different. As a consequence I'm using the URL to internally separate out clients, and an overridden Razor view engine (at least in terms of finding the view) to automatically select either a customised view for a given action, or the default view.
To help 'compartmentalise' a complex page, any particular view will make use of several partials, usually rendered as self-contained actions, so that generally a custom view or partial view will only have small HTML differences, helping to minimise any code specific to a client's site.
I hope you followed that background!
So one HTML page might be made up of lots of little smatterings of HTML partial views, which could come from specific folders for the client, or a general-purpose version. I'm hoping to make it easier for our designer to make minor changes to a page by easily seeing where in the folder structure the bit of HTML he wants to change are.
My proposal then is that each partial will be 'bracketed' with HTML comments such as:
{ Content of partial }
Obviously I could put these in manually, but that's just asking for trouble, for typos, for copied and then modified client versions not being updated with the correct URL. It should be possible to get this from some context and inject it, I think.
At the same time, I need to be able to not do this for certain Actions. Eg, a partial might be generating text inside a textarea, say, so the comments wouldn't be appropriate there. On the whole I'm happy to put these comments in unless I specify that it's not appropriate.
For me this suggests an ActionFilter on an Action, which I can apply site wide and then turn off for certain Actions. I'd hope that one of the overridable events would let me ascertain this path, but I can't seem to find anywhere it's stored. Furthermore, OnResultExecuting seems to fire before the Partial has been selected, and OnResultExecuted seems to have already written out the contents of the Partial, so I can't insert the starting comment here. I also can't find any reference to the path of the selected partial.
Just for completeness, it's my intention that this attribute would only write these comments when compiled in Debug mode.
So, does anyone know how I might be able to get the path to the selected View without any kind of hack between FindPartialView and the Attribute? Is my Attribute method the best choice or is there an easier way to do this? Perhaps something's built in already!
Many thanks for your help.
Well, I've never forgotten about wanting this, and always hoped I'd solve it one day, and thankfully I have.
I've overridden the default WebViewPage (I use the Razor engine), and in particular ExecutePageHierarchy to inject the comments:
public abstract class PaladinWebViewPage : PaladinWebViewPage<dynamic>
{
}
public abstract class PaladinWebViewPage<TModel> : WebViewPage<TModel>
{
public bool DisplaySourceCodeComments
{
get { return ((bool?) ViewBag.__DisplaySourceCodeComments) ?? false; }
set { ViewBag.__DisplaySourceCodeComments = value; }
}
public override void ExecutePageHierarchy()
{
base.ExecutePageHierarchy();
// Filters can be used to set and clear this value so we can decide when to show this comment
if (!DisplaySourceCodeComments) return;
var sw = Output as StringWriter;
if (sw == null) return;
var sb = sw.GetStringBuilder();
sb.Insert(0, string.Format("<!-- Start of {0} -->", VirtualPath));
sb.AppendFormat("<!-- End of {0} -->", VirtualPath);
}
VirtualPath tells us the exact file used to build the HTML, so we can inject the filename before and after. This isn't doing anything at the moment, since the default is to not show comments (the "?? false" in DisplaySourceCodeComments).
Also to use this view page you need to edit Views/Web.config and change the pageBaseType to this type.
I want to selectively turn these comments on and off so I've created an ActionFilter:
public class DisplaySourceCodeCommentsAttribute : ActionFilterAttribute
{
private readonly bool _displaceSourceCodeComments;
public DisplaySourceCodeCommentsAttribute(bool displaceSourceCodeComments)
{
_displaceSourceCodeComments = displaceSourceCodeComments;
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
var viewResult = filterContext.Result as ViewResultBase;
if (viewResult == null) return;
viewResult.ViewBag.__DisplaySourceCodeComments = _displaceSourceCodeComments;
}
}
I'm slightly unhappy that I've had to use the ViewBag here and also separately in the view page override, as they aren't tightly linked, but I can't find a way for the filter to directly interact with the view page, so this is something of a necessary fudge. It does have the benefit that displaying source code for a view or partial also automatically displays it for any child partials until you turn it off again, since the ViewBag is passed down the chain.
With this in place, any action can turn on the source code comments with
[DisplaySourceCodeComments(true)]
or, obviously turn it off again with false
The Attribute checks that the context result is a ViewResultBase, which means just Views and Partials, so Json or Content or redirects aren't affected, which is very handy too.
Finally, I make this action filter a global when running in debug mode so that every view, and partial has the source comment included, by adding the following line to global.asax.cs:
[#]if DEBUG
// When in debug mode include HTML comments showing where a view or partial has come from
GlobalFilters.Filters.Add(new DisplaySourceCodeCommentsAttribute(true));
[#]endif
I'm really happy I've finally got it sorted so I hope this is useful for someone else.

One EditPart for all model views (in GMF/GEF)

We're working on creating a modeling tool based on the GMF framework and tools. We have a requirement to allow users to add views (figures) at runtime and use them in their diagrams. We will be using SVG files to represent figures.
What's the correct structure of EditParts and other GEF related classes in such a case? We were thinking of implementing a single GEF EditPart class, that would create the appropriate figure based on a parameter (path to SVG file) present in the model. So far it doesn't seem to be working.
There HAS to be someone who's already done something like this before. Googling and the Eclipse forums have not been helpful so far...
Well we found a (partial) solution. We have one element, and depending on a parameter we create a child figure inside it, which uses an SVG file (based on the parameter).
The following test code is called in the constructor of the Figure:
ScalableImageFigure svg; URL url;
if (type == 1) { url =
ArchitectureStudioDiagramEditorPlugin.getInstance().getBundle().getEntry(
"icons" + IPath.SEPARATOR + "shadow-box.svg"); } else { url =
ArchitectureStudioDiagramEditorPlugin.getInstance().getBundle().getEntry(
"icons" + IPath.SEPARATOR + "star.svg"); } svg = new
ScalableImageFigure(RenderedImageFactory.getInstance(url),
true, true, true);
this.add(svg);
Now we need to figure out how to have multiple elements in the Palette.
The correct way is to have one to one mapping between figure and editpart . Also painting task should be left to the figure . How the image should be painted , the logic must be inside the figure not in the editpart.
Thanks

Resources