Missing certain #helpers in Views ASP.net MVC3 - asp.net-mvc

I'm having an excessively strange issue.
I'm working on a project and it's being converted to use asp.net MVC.
Everything works the controllers/models/views. I get every keyword possible in the controller (ViewBag, ViewContext, etc.).
In my views, however, I only get some helpers (e.g. #Model, #Html), but I'm missing others (#model, #ViewBag, #ViewContext, etc.)
It's an enormous hinderance (i'd post code but I don't know what code is really relevant). My web.config is 100% dead-on and all of my other MVC projects do not have this issue.
Web.Config is correct(in the Views folder)
Target framework is correct
I have access to all of the methods in my controllers
I've cleaned the project/re-mapped it, etc. Others on other machines do not have this issue, but oddly I do (I've entirely re-checked out the project).
Like I said, i don't know what code is relevant I'm just hoping someone else has an idea as what can be wrong. I'm baffled since the web.config is right, i'm not missing any references (all my references are pointing to the correct location), and I can use all of them in the controller.
Just because I don't want to get yelled at, here's an excerpt from my web.config in the Views/ folder
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
</namespaces>
</pages>
</system.web.webPages.razor>
One of the strangest issues i've ever experienced :O
Sample:
#model Project.WebUI.Models.MyModel
#{
ViewBag.title = "hi";
}
<div>#Model.someItemInTheModel</div>
model is red underlined 'does not exist in current context'
#model Project.WebUI.Models.MyModel
ViewBag is red underlined 'does not exist in current context'
ViewBag.title = "hi";
This line is perfectly fine
<div>#Model.someItemInTheModel</div>
Controller, this is all perfectly fine
public ActionResult MyView(long date)
{
MyModel model = new MyModel();
model.someItemInTheModel = "hi";
return PartialView(model);
}

Create a new MVC3 project and compare those web.config files to the ones in your project. You'll need the check the in the project root (/web.config) and in /Views/web.config.
Also check to make sure you have all of the same System.Web.* references.

Related

Accessing data from web.config (in views folder)

I'm working on an MVC application and in a particular section of the website I need to send notification emails (I'm guessing maybe a maximum of 10). So I thought that I'd save the emails as a list in the web.config file and then loop through the list to send emails.
I first tired creating a custom section and adding the data I needed (in the main web.config file) like so (Reference):
My Code:
web.config file:
<configSections>
<section
name="AdminEmails"
type="System.Configuration.NameValueFileSectionHandler,System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections>
<AdminEmails>
<add key="email1" value="test#test.com" />
<add key="email2" value="abc#abc.com" />
<add key="email3" value="email#email.com" />
<add key="email4" value="username#domain.com" />
</AdminEmails>
Code in controller:
NameValueCollection section =
(NameValueCollection)ConfigurationManager.GetSection("AdminEmails");
//... loop through emails in 'AdminEmails' section...
But then I got an error stating that there cannot be duplicate <configSection> as there already was a <configSection> in the other web.config file. So instead I added the data in the web.config file saved in the views folder. The website ran however the section variable was null. I'm thinking this is because ConfigurationManager.GetSection() tried to get a section from the 'main' web.config file. I don't know if it's possible a way to access the web.config file saved in the views folder via code.
As far as I know you cannot access the web.config inside the Views folder from controller, it is designed to be used in descending Views folders scope.
Anyway the error you are getting says that you are defining a duplicate section, so try to add your custom section after the existing sections in root web.config, for example:
<configuration>
<configSections>
<!-- YOUR SECTION -->
<section name="AdminEmails" type="System.Configuration.NameValueFileSectionHandler,System, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<!-- EXISTING SECTIONS -->
<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"></sectionGroup>
</sectionGroup>
</sectionGroup>
</configSections>

AppFabric configuration issue with dataCacheClient vs dataCacheClients

I'm trying to get AppFabric working in my Asp.net application, everything works fine if I use c# code to do the configuration. But I'm having a real hard time to get it to work from web.config. If I have the following in the web.config,
<section name="dataCacheClient"
type="Microsoft.ApplicationServer.Caching.DataCacheClientSection,
Microsoft.ApplicationServer.Caching.Core, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"
/>
and
<dataCacheClient>
<hosts>
<host name="localhost" cachePort="22233" />
</hosts>
</dataCacheClient>
then my code does not throw exceptions, HOWEVER doing put to the default cache does not actually put anything into the cache, byte count is 0.
If I change the web.config to
<section name="dataCacheClients"
type="Microsoft.ApplicationServer.Caching.DataCacheClientSection,
Microsoft.ApplicationServer.Caching.Core, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"
/>
notice the it's "dataCacheClients" with an "s" and
<dataCacheClients>
<dataCacheClient name="default">
<hosts>
<host name="localhost" cachePort="22233" />
</hosts>
</dataCacheClient>
I got exception
ErrorCode<ERRCA0021>:SubStatus<ES0001>:Server collection cannot be empty
Could someone help point out what I'm missing here.
Thank you so much!
Your first example is correct, just add parameters:
allowLocation="true"
allowDefinition="Everywhere".
<section name="dataCacheClient"
type="Microsoft.ApplicationServer.Caching.DataCacheClientSection,
Microsoft.ApplicationServer.Caching.Core, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"
allowLocation="true"
allowDefinition="Everywhere"/>

MEF and Razor Views inside Class Library

I have a composite ASP .NET MVC 3 Razor application using MEF. Everything goes fine if I am to deploy plugins as DLL files and views (CSHTML) under the regular Views folder from the application. But this is not very clean and it won't be a real plugin if I don't place views as embedded resources within the DLL files (along with both controllers and models).
I've followed many articles (most of them are outdated). In fact there is one quite good one here on Stack Overflow: Controllers and Views inside a Class Library
I've also checked docs for VirtualPathProvider and I've been able to build a custom one that finds the file within the assembly and loads it perfectly (or at least gets the stream to it). For this I've followed the VirtualPathProvider documentation on MSDN.
There is also an implementation for VirtualFile but not yet for VirtualDirectory.
Here is the problem. I'm working with Razor views. I do know that they need config specs from the web.config file for Razor to build them. But if I embed them within the DLL this config is simply lost.
I wonder if that's why I keep getting the error:
The view at '~/Plugins/CRM.Web.Views.CRM.Index.cshtml' must derive
from WebViewPage, or WebViewPage.
Maybe I just need to add some code to make it work? Any ideas?
My preferred way to embed Razor Views in a Class Library is to copy them into the MVC website's Views/Areas folders with a post build event. Custom view locations can be specified if you override the ViewEngine or VirtualPathProvider.
The tricky part for me was getting intellisense to work in these View Class libraries. First, you must add a Web.Config to your View assembly. Note that you don't have to actually include it in your assembly. It only has to be in the assembly root directory (or views folder). Here is an example. Regard the important Assemblies/Compilation section.
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
</namespaces>
</pages>
</system.web.webPages.razor>
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>
<system.web>
<compilation targetFramework="4.0">
<assemblies>
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add assembly="System.Data.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</assemblies>
</compilation>
<httpHandlers>
<add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
Enabling request validation in view pages would cause validation to occur
after the input has already been processed by the controller. By default
MVC performs request validation before a controller processes the input.
To change this behavior apply the ValidateInputAttribute to a
controller or action.
-->
<pages
validateRequest="false"
pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<controls>
<add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
</controls>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
</handlers>
</system.webServer>
</configuration>
Next, you need to modify your class library's vbproj file so that all OutputPath elements point to 'bin\' instead of 'Debug\bin\' or 'Release\bin\'. This is the main difference I found between class libraries and ASP.Net web project types that can cause intellisense bugs.
If you still recieve your must inherits error, consider using #Inherits System.Web.Mvc.WebViewPage in your views. If you are not copying your views into your website project, you may be loading them from Embedded Resources using a custom ViewEngine / VirtualPathProvider. If that is the case, you definately need the Inherits so Razor knows what your view base class is unfortunately.
Good luck.
You might take a look at the following blog post.
Hossam,
The post you're talking about is what Darin has already suggested. The main down side to that approach is using the custom MvcRazorClassGenerator compiler to convert the CSHTML view files in to class files. To do so you have to set every CSHTML view in your project to Content and set the Custom Tool to MvcRazorClassGenerator.
I can't speak for LordALMMa but I did download the compiler source and gave it a shot and it doesn't exactly work the way I was hoping.
My other approach was to include the CSHTML files as Embeded Resources in the external DLL, read in the raw contents of the file and execute the view as a string (See the RazorEngine on CodeProject for an example: http://razorengine.codeplex.com/)
I didn't want to fully depend on the RazorEngine in an enterprise application because I don't know how well it is compatiable with all of the Razor syntax so I gave up on that for now.
I'm coming from a prototype I built in ASP.NET MVC 2.0 that is a multi-tennant application. On a server farm we have one instance of an application running where all clients share the same code base. In my MVC 2.0 prototype I was able to determine what "client" the request was being made for, check for a custom controller that over-rides the base (for customizations of the core code) and also check for custom views (for customizations of the core view). What this does is allow us to deploy a "plugin" per say for each client. The software detects if the client has a custom controller that matches the request as well as a custom action that matches and if it does, it uses the customized controller/action instead.
When I started migrating my prototype to MVC 3 I ran in to the same problem as LordALMMa, the error "The view at '...Index.cshtml' must derive from WebViewPage, or WebViewPage". I'll look in to placing "#inherits System.Web.Mvc.WebViewPage" on my CSHTML views and see if that gets me any closer to getting it to work.
Since I have a working MVC 2.0 prototype using MVC 3 Razor is not a top priority and I don't waste a ton of time on it. I'm sure I can port the MVC 2.0 to MVC 3.0 using the WebForms engine if we need to leverage the 4.0 Framework.
Hey I suspect you have good reasons for wanting views inside DLLs. However also consider that it is an unusual way of packaging everything into one entity.
If you are developing a plugin, these days people opt for packaging in the NUGET format, which also solves your kind of problem among other things. It has a .nupkg structure which is also one way of distributing plugins as packages and libraries.
Another solution which communities generally follow is (if they do not want something as elaborate as nuget) they code up the plugin DLLs such that, it does not use view engines like razor, instead outputs HTML all by itself using the old primitive way of Response.Write and thus become independent of cshtml files. If you still want to use cshtml - see this blog entry for precompiling those into classes.

MVCContrib Portable Area No Intellisense for ViewPage<T>

I am trying out portable areas using MVCContrib.
In general these work well and it seems to be a good way to share controllers\views between web projects.
The only problem that I'm having is that Intellisense (specifically, for the HtmlHelper) is not working in the view for strongly typed views i.e. ViewPage.
The intellisense does work however when the view is a plain 'ol System.Web.Mvc.ViewPage
A similar questions has been asked here:
MvcContrib Portable Areas View Intellisense?
But these suggestions don't seem to make any difference.
I am using MVC 2, the portable areas are in their own class library as in the MVCContrib sample code.
I'd also like to add that the MVC sample code gives me the same behaviour, if I change the sample project to make the view page strongly typed then intellisense stops working.
Are other people having the same problem ?
Does anyone know the cause and or solution ?
the web.config from my Views folder is as follows:
<?xml version="1.0"?>
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
Enabling request validation in view pages would cause validation to occur
after the input has already been processed by the controller. By default
MVC performs request validation before a controller processes the input.
To change this behavior apply the ValidateInputAttribute to a
controller or action.
-->
<pages
validateRequest="false"
pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<controls>
<add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
</controls>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
</configuration>
This was a problem with ReSharper intellisense in VS2010, ReSharper v5.0.
If I change my ReSharper options (ReSharper->Options->Intellisense->General) to use Visual Studio intellisense then it works!!

ASP.NET MVC Strongly Typed Partial View, gives could not load type error

I am attempting to create a strongly typed view with a "MVC View User Control" that is being rendered using Html.RenderPartial(). The top of my ascx file looks like this:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.Collections.IEnumerable<string>>" %>
There is nothing else on this page, currently.
When I execute the app and load the page that renders this control, I get the following error:
Could not load type 'System.Web.Mvc.ViewUserControl<System.Collections.IEnumerable<string>>'.
So, then I simplified it:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<String>" %>
And then, just in case it needed to be fully qualified:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.String>" %>
Everytime I get the same error (substituting type). what am I doing wrong here? I'm on .NET 3.5 with ASP.NET MVC 1.0 RTM.
I got it working. I followed the instructions from http://www.codewrecks.com/blog/index.php/2009/04/05/could-not-load-type-systemwebmvcviewpage/ and that did the trick for me. I should note that I also upgraded to the ASP.NET MVC 2.0 RC as of 3/17/2010 first. The problem persisted for me still until I followed the instructions on that page. I'm not sure if a fresh MVC project does this for you now or not.
The solution, in case the referenced page goes away, was to add a Web.config to my Views directory, and put this in it:
<?xml version="1.0"?>
<configuration>
<system.web>
<httpHandlers>
<add path="*" verb="*"
type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<!--
Enabling request validation in view pages would cause validation to occur
after the input has already been processed by the controller. By default
MVC performs request validation before a controller processes the input.
To change this behavior apply the ValidateInputAttribute to a
controller or action.
-->
<pages
validateRequest="false"
pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<controls>
<add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
</controls>
</pages>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
</handlers>
</system.webServer>
</configuration>
I should also note that for MVC 2.0 you need to update the version #'s in the config.

Resources