Turning off the WebFormViewEngine when using razor? - asp.net-mvc

I downloaded Glimpse this morning to try it out and noticed this when I click on the views tab:
It checks all of the loaded view engines. I found where the RazorViewEngine is specified in web.config, but I couldn't find where the WebFormViewEngine was. Since I know my project will never have an web form view in it,
Is it ok/safe to turn off WebFormViewEngine?
How can I turn off WebFormViewEngine?

It is perfectly OK to remove the web forms view engine if you are not using it. You can do it like:
public class Global : HttpApplication
{
public void Application_Start()
{
// Clears all previously registered view engines.
ViewEngines.Engines.Clear();
// Registers our Razor C# specific view engine.
// This can also be registered using dependency injection through the new IDependencyResolver interface.
ViewEngines.Engines.Add(new RazorViewEngine());
}
}
The above method calls go in your global.asax file.
source of code

An alternative would be to remove only the view engine you want to remove:
var webformVE = ViewEngines.Engines.OfType<WebFormViewEngine>().FirstOrDefault();
ViewEngines.Engines.Remove(webformVE);

Related

How do you instantiate Pages that have constructors in UWP?

I want to use the Navigation feature in UWP. Unfortunately, the argument to the Navigate method is a type, not an instance of a page. It looks like the activation of this type is done behind the scenes. I question the design decision, but my immediate problem is that all my MVVM forms are instantiated with the view model. Typically I create pages using the Dependency Injection container.
How do you create pages in UWP when they're used with the Navigate method when those pages have DI constructors?
How do you create pages in UWP when they're used with the Navigate method when those pages have DI constructors?
Instead trying to navigate to the page based on its type, you could set the Content of the Frame to an instance that you create yourself:
rootFrame.Content = new YourPage(yourDependency);
The other option is to make sure that all your pages have a default parameterless constructor and inject the dependencies somewhere else, for example in the OnNavigatedTo method as suggested by #Richard Zhang - MSFT.
In UWP, the navigation parameters of Frame.Navigate are Type rather than instances. This is really a design.
In fact, navigating in UWP doesn't require instances, as well as DI, and in general, if you need to combine Page and ViewModel, you can do this:
1. Initialize ViewModel inside the page constructor
Frame
MyFrame.Navigate(typeof(MyPage));
MyPage
private MyViewModel vm;
public MyPage()
{
this.InitializeComponent();
vm = new MyViewModel();
}
2. Initialize ViewModel by passing parameters when navigating
Frame
var vm = new MyViewModel();
MyFrame.Navigate(typeof(MyPage), vm);
MyPage
private MyViewModel vm;
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if(e.Parameter!=null && e.Parameter is MyViewModel _vm)
{
vm = _vm;
// do other things
}
}
If you want to reuse pages, you can enable page caching, it will save the current page state (including ViewModel), and use the cache when you next navigate to the page, so you can avoid repeatedly creating ViewModel.
public MyPage()
{
this.InitializeComponent();
NavigationCacheMode = NavigationCacheMode.Enabled;
}
Best regards.

Configuration(IAppBuilder) not firing on start up

The configuration method below doesn't get fired.
using Microsoft.Owin;
using Owin;
[assembly: OwinStartupAttribute(typeof(SCM.Web.Startup))]
namespace SCM.Web
{
public partial class Startup
{
public void Configuration(IAppBuilder builder) { }
}
}
I've followed all the hints from here and it's a new project, not an upgrade. I can't for my life see how to get it to stop on the breakpoint and I'm in need to get more suggestions on how to troubleshoot it.
It's an intranet application so there's no logging in. The identity gets set to the Windows credentials, instead. I need to assign the roles so that only certain users can access certain actions in the controllers. I'm usually applying OWIN and application cookies, so that's the method I'm trying to follow here, as well.
You need an OwinStartup attribute to tell Owin what method to call. From the docs:
Used to mark which class in an assembly should be used for automatic startup.
Add one to your project, before the namespace declaration:
[assembly: OwinStartup(typeof(Your.Namespace.Startup))]
namespace Your.Namespace
{
public partial class Startup
{
public void Configuration(IAppBuilder builder) { }
}
}
There are some other methods to let Owin know which method (described here) but this is the simplest and probably the most common.
If you are running the website on an external IIS or maybe on the "real" IIS installed on your computer (and not the one that is fired up when you start the run), then it's likely that you're missing the breakpoint because the debugger isn't attached to the process yet when you pass by.
I think that you can confirm it by either checking the settings of your solution and projects or simply adding this code to the method that you don't think that you pass through.
throw new Exception("Killroy was here...");

unity.mvc4: how to get a reference

I've setup Unity in Bootstrapper.cs of my MVC application, all is working well for constructor injection on my controllers...
My question is when I'm in an ActionResult within a controller I need to get a reference to the container I previously created in Bootstrapper.cs so I can use it to resolve classes for me.
e.g:
public ActionResult Index()
{
//-- container needs a reference to unity container
var testService = container.Resolve<ITestService>();
return View(testService);
}
I need to get a reference to the container
No you don't. You should never need to reference the container (or the DependencyResolver) from within your application.
Use constructor injection instead:
public class HomeController : Controller
{
private readonly ITestService testService;
// constructor
public HomeController(ITestService testService)
{
this.testService = testService;
}
public ActionResult Index()
{
return View(this.testService);
}
}
Since you are using the MVC3 integration package for unity, you probably registered a Unity specific DependencyResolver in the startup path of your application. That looks much like this:
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
When you've done this, your custom DependencyResolver will delegate the creation of controllers to the Unity container and the Unity container is able to inject depdencies of the constructor's of the controllers.
The next thing you should never do is letting views do any work and making them dependent on your services. Views should be dumb and do nothing more than map the data they get from the controller and transform them to HTML (or JSON or whatever).
In other words, do not pass on the testService to the view. Calling the testService from within the view hides that logic, makes the view more complicated, and makes the system hard to test. Since you're using an ITestService abstraction, I assume you want to be able to test your code, but testing the view is not easy (or at least, not as easy as you can test the controller).
What you should do is let the controller call the testService and gather the data that is needed for the view to use. Than pass on that data (perhaps combined in a single class, a view model) to the view.

ASP.net MVC - using custom culture - resources not being loaded

I have an ASP.net MVC site, which I want to use a couple of resource files to set some strings.
I have a class library containing my viewmodels, and I have added a resource file (ValidationMessages) there, with a single string (called Test), and then have a property like so in my view model:
public string TestResource
{
get
{
return ValidationMessages.Test;
}
}
And that works fine, when output on my view like so:
<div>#Model.TestResource</div>
If I add a ValidationMessages.en-au.resx (my default would be en-gb) file to my class library and create a different version of the test string, and then have the following in my global.asax:
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-au");
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-au");
}
And this also works fine.
What I want to do is add a custom culture 'en-gb-ly' - I have registered this culture on my machine ok (using code from here). When I set the current culture to "en-gb-ly" in my global.asax and include a ValidationMessages.en-gb-ly.resx in my class library, the output has reverted back to the 'base' version of the Test string, not the one in my en-gb-ly resource.
Anybody any idea why this might be happening?
A first thing to check is that the en-ly satellite assembly gets deployed as expected. Unfortunately if your custom culture is not installed on your build machine, then it won't even get built!

Is there any way to re-use editor & display templates in asp mvc applications?

We're developing 3 asp mvc applications, all will require some of the same shared editor & display template views. Rather than copy/paste these across all 3 projects, is it possible somehow to put them in a shared component and reference them somehow in all applications?
You're going to need to create your own ViewEngine if you want to take to views from a place other than the Views folders.
public class CustomViewEngine : WebFormViewEngine {
public CustomViewEngine() : base() {
MasterLocationFormats = new[] {
"/YourFolder/{1}/{0}.master",
"/YourFolder/Shared/{0}.master"
};
ViewLocationFormats = new[] {
"/YourFolder/{1}/{0}.aspx",
"/YourFolder/{1}/{0}.ascx",
"/YourFolder/Shared/{0}.aspx",
"/YourFolder/Shared/{0}.ascx"
};
PartialViewLocationFormats = ViewLocationFormats;
}
//Override the FindView method to implement your own logic
public override ViewEngineResult FindView(
ControllerContext controllerContext, string viewName,
string masterName, bool useCache)
return base.FindView(controllerContext, viewName, masterName, useCache);
}
}
Then to register your ViewEngine in the Global.asax :
protected void Application_Start() {
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomViewEngine());
}
Also, this post might be helpful. (too bad the download link at the bottom is broken though)
Edit : It appears this solution won't work in practice, since ASP.NET won't allow loading content from outside of the application's directory (see Eilon's comments).
But the link above, storing views in DB, could still be helpful.
I am not sure how it can be done but there must be a way to compile the pages in a DLL and share the library.
But if you can afford to use custom view engine and another template system (for example Stringtemplate) then you can share the views as if you are sharing a library:
Create a class library project
Create your templates as normal and mark them as 'Embedded resource'. This will make sure they will be put in the library's DLL
Write your custom view engine to pull the templates from the assembly (DLL). A good start might be editing/forking an existing one: http://code.google.com/p/string-template-view-engine-mvc/source/browse/trunk/StringTemplateViewEngine/StringTemplateViewEngine.cs
Then register your view engine in your ASP.NET MVC project
To share user controls (or almost any content) between multiple ASP.NET applications you can use the trick listed here: http://aspadvice.com/blogs/ssmith/archive/2006/10/05/Tip_3A00_-Share-User-Controls-Between-Applications-in-ASP.NET.aspx
The basic idea is to place the ASCX files in a folder and make that folder in to a virtual folder of other applications (you can have multiple virtual folders pointing at the same physical folder).

Resources