Using enum in #Url.Action() routevalues - c#

This question is just a quick one. I have a set of links on a page, and they all actually point to the same controller method - the difference between them is that they each pass a different value to that method so that the subsequent process is slightly different. I happened to already have an enum defined to correspond to the possible values passed, so without thinking, I did this:
#Url.Action("QueryStepTwo", new { type = QueryType.UserRecords })
and was pleasantly surprised to see that nothing gained a red underline. I hit compile and navigated to that page to verify, to be presented with an error message for CS0103: "The name 'QueryType' does not exist in the current context". In the editor, QueryType is syntax-highlighted and IntelliSense provides the options list when I type it.
I'm assuming this is just a case of VS/IntelliSense being just a little bit too smart and knowing things that the actual page parse/render engine can't? Casting the enum to its string or int value doesn't help, so I'm guessing this is to do with the order in which things are executed; more specifically, the enum is out of scope by the time Razor gets to see the page. Is there a way to use an enum in URL helpers like this, especially one that doesn't require the enum to be defined as a member of the view model? I dislike using magic strings all over the place; they're too vulnerable to typos and tomfoolery.

Make sure you fully qualify the namespace where this enum is defined:
#Url.Action("QueryStepTwo", new { type = SomeNamespace.QueryType.UserRecords })
or if you don't want to do that you could also add an #using directive to the top of your Razor view:
#using SomeNamespace
And if you want to do this globally for all Razor views you could add this namespace to the <namespaces> node in ~/Views/web.config (not to be confused with ~/web.config):
<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" />
<add namespace="SomeNamespace" />
</namespaces>
</pages>
</system.web.webPages.razor>
As far as the Intellisense in Razor views is concerned, this is not something that could be trusted. Hopefully Microsoft will improve it in future versions.

Related

Could not load type System.Web.Mvc.ViewUserControl<somethig>

I spend all day trying to find the solution. I found some but none of it worked for me. Long short the application I am working on is being upgraded from MVC3 (I believe) to MVC5 and ASP.NET Version 4.6.1. The upgrades were being done by some other developer and now I have to fix all issues and bugs he left. The issue I am facing is that I can't load strongly typed view. I invoke the action method from my main view:
<div id="fromLocationEditPartial">
#Html.Action("FormLocationEdit", "Shared", new { area = "Shared", options = Model.LocationID });
</div>
Here is the action method code I am calling:
public ActionResult FormLocationEdit(int? options)
{
LocationEditorModel model = new LocationEditorModel();
//DTLocationAutoMetadata locObj;
DTLocation locObj;
if (options.HasValue)
{
int locationID = options.Value;
//locObj = AutoMapper.Mapper.Map<DTLocation, DTLocationAutoMetadata>(entities.DTLocation.Where(m => m.LocationID == locationID).FirstOrDefault());
locObj = entities.DTLocation.Where(m => m.LocationID == locationID).FirstOrDefault();
if (locObj == null)
{
locObj = new DTLocation();
locObj.SelectLocation = new SelectList(model.GetListOfLocations(), "Value", "Text");
}
else
{
locObj.SelectLocation = new SelectList(model.GetListOfLocations(), "Value", "Text", locObj.SiteID);
}
}
else
{
locObj = null;
}
return View("~/Areas/Shared/Views/FormLocationEdit.ascx", locObj);
}
Here as you can see it suppose to return the strongly typed view with object.
Here is how my shared view looks like:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<CMDBv3.DTLocationAutoMetadata>" %>
<script type="text/javascript">
$(document).ready(function () {
//BindSubmitActions('formLocationEdit');
})
</script>
<% using (Html.BeginForm("FormLocationEdit", "Shared", FormMethod.Post, new { area="Shared", id = "formLocationEdit" })) {%>
***here is the condition if (Model!=null) do something else display model data***
In my VS Error list I am having errors:
Error 4 The name 'Model' does not exist in the current context
Error 2 The name 'Html' does not exist in the current context
When I run the proj I am getting inner exception:
Could not load type System.Web.Mvc.ViewUserControl"<"CMDBv3.DTLocationAutoMetadata">"
As I understand it is some issues with versioning but I checked all my web.config and it seems that version is fine there. Can someone give me some advice what else could it be if it is not web.config issue?
I have similar problem in the past when upgrading MVC 3 (or 4) project using ASCX shared user controls inside area into MVC 5 with Razor views enabled by default (missing ViewUserControl namespace), hence I trying to add these lines below on web.config file inside Views directory of that area and working properly then:
<system.web>
<pages validateRequest="false" pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<controls>
<add assembly="System.Web.Mvc, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
</controls>
</pages>
</system.web>
NB: This change also apply to other area views' web.config containing ASPX page/ASCX controls which inherit System.Web.Mvc.ViewPage/System.Web.Mvc.ViewUserControl.
Then, in that area view's web.config, ensure these lines added between system.web.webPages.razor element:
<system.web.webPages.razor>
<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>
To solve "Model doesn't exist" issue, you can change this line in project's web.config:
<add key="webpages:Version" value="1.0.0.0" />
To this line:
<add key="webpages:Version" value="3.0.0.0" />
For further info about upgrading to MVC 5, check MVC 5 Upgrade Guide.
PS: The missing namespaces problem often occurs when web.config file inside Views directory (including area views) not included or not created yet. Also if you're still not sure try setting Copy Local = True in reference properties related with System.Web.Mvc namespace. After all, seems it is easier to create a new predefined MVC 5 project and resolving relevant existing resources into that.
Related issues:
Could not load type 'System.Web.Mvc.ViewUserControl<SOMETYPE>'
"The name 'HTML' does not exist in the current context" in MVC 3 Views
Razor View throwing "The name 'model' does not exist in the current context"
The way I solved it just simply created cshtml view and use razor syntax:
#model CMDBv3.DTLocation
#using (Html.BeginForm("FormLocationEdit", "Shared", FormMethod.Post, new {
area = "Shared", id = "formLocationEdit" }))
and that worked for me.

Implicit namespace and service reference

I've got a service reference of type ServiceReference in the namespace MyNamespace, containing some data classes' definitions. That leads to the following syntax in my CSHTML file.
#foreach(MyNamespace.ServiceReference.MyDataType blopp in ViewBag.Blopps) ...
This is less than convenient and I'd like to be able to go like this, instead.
#foreach(MyDataType blopp in ViewBag.Blopps) ...
In a CS file, I'd apply using for this but what's recommended approach for the CSHTML file?
EDIT
Of course, besides #using MyNamespace.ServiceReference; :)
Use:
#using MyNamespace.ServiceReference
EDIT:
Since in your edited question you specified, besides #using, you can add the references in web.config file but they will be available for all the views.
<system.web.webPages.razor>
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<!-- Add following with others -->
<add namespace="MyNamespace.ServiceReference" />
</namespaces>
</pages>
</system.web.webPages.razor>

Razor to talk to class function?

I am trying to add social networking buttons to my site and have build a socialNetworkingHelper class.
I would like to know what i need to do to get the view to see the helper class.
I followed the following link to get where i am now.
http://www.advancesharp.com/Blog/1033/add-facebook-twitter-and-google-plus-in-c-mvc-application
I am using MVC 4 and have placed this div in my layout page in my footer.
<div>
#Html.SocialLinkButtons(Model.Title, Request.Url.ToString())
</div>
The SocialLinkButtons text is underlined in red with the following error message.
'System.Web.Mvc.HtmlHelper' does not contain a definition for
'SocialLinkButtons' and no extension method 'SocialLinkButtons'
accepting a first argument of type
'System.Web.Mvc.HtmlHelper' could be found (are you missing
a using directive or an assembly reference?)
Is there somthing i must add to my view to allow the #html to call my socialLinkButtons?
Or is there something i need to add to my class to allow this?
I have tried placing my class in the contoller folder and the models folder and just plain in the whole project. Where should this helper class be kept?
To see the class please follow the link placed above.
Edit:
Following the answers below the SocialLinkButtons text is no longer underlined but when i run my code i get the following error.
'System.Web.Mvc.HtmlHelper' has no applicable method named
'SocialLinkButtons' but appears to have an extension method by that
name. Extension methods cannot be dynamically dispatched. Consider
casting the dynamic arguments or calling the extension method without
the extension method syntax.
You shoud to put code from link in any namespace:
namespace Helpers {
public static class SocialNetworkingHelper {
...
}
}
and add using directive in your view:
#using Helpers
Probably you extension method SocialLinkButtons is not visible in the view.
You should add #using MyNamespace directive in the view where MyNamespace is actual namespace of your extension method SocialLinkButtons or youcan achieve the same thing via web.config by adding this namespace to
<system.web.webPages.razor>
<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" />
<add namespace="System.Collections" />
<add namespace="MyNamespace" />
</namespaces>
</pages>
</system.web.webPages.razor>

Getting a HttpCompileException in ServiceStack Razor view (Self hosted)

ASSEMBLY 1
This is my project structure (I serve up content from embedded resources):
Common_Assembly.dll
Css
Common.css
Views
Shared
_Layout.cshtml
This also has a class called Model.cs, which is essentially just:
public class Model
{
public string Title {get; set; }
}
_Layout.cshtml
#model MyNameSpace.Model
<html>
<head>
<script language="javascript" href="css/common.css"></script>
<title>#Model.Title</title>
</head>
<body>
#RenderBody
</body>
</html>
ASSEMBLY 2
I then have a second assembly (which references the one above) and is the one that actually hosts the web-service:
Concrete_Assembly.dll
Views
Index.cshtml
This has a class called IndexResponse that derives from Model in the other assembly.
public class IndexResponse : Model
{
}
Index.cshtml
#Model MyOtherNameSpace.IndexResponse
<p>Test</p>
Now, the problem. If I remove the #Model line, everything works correctly and I see my index page within the layout page of the other DLL (I use a custom VirtualPathProvider to locate resources across multiple Dlls). However, if I try and use the IndexResponse as a model in the index page, I get a HttpCompileException. As it is thrown by an external component I do not actually know what the exception message is (I use service stack binaries).
At first I wondered if it was because the model class was different from the layout's class (even though it derives from it). To test that theory I created a TestModel class that derives from Model (placed IN the common assembly), and used that - it worked fine.
This leads me to believe it is because the IndexResponse is in the secondary assembly - but can't be sure because I can't see the error.
Any help would be appreciated!
EDIT
For completeness, here is the actual WebService method. I do not believe anything is wrong here as it worked fine when I did my other tests (using TestModel instead).
public IndexResponse Any(Index index)
{
return new IndexResponse() { Title = "Test Title" };
} // eo Any
EDIT 2
Apologies for all the edits. Furthermore, is there anyway I can get hold of this exception or handle it so I can have a look at the error? It would be nice to catch this and display it - otherwise developing these pages as embedded resources is going to be like pulling teeth :)
EDIT 3
After following some suggestions from Mythz, and adding the correct namespaces in to the Razornamespaces configuration, I have finally gotten hold over the error that it is throwing:
+ $exception {"(0): error CS1704: An assembly with the same simple name 'Concrete_Assembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null has already been imported. Try removing one of the references or sign them to enable side-by-side."} System.Exception {System.Web.HttpCompileException}
`
If you haven't already you should add any assemblies you're using to your app.config, e.g:
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc,
Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="ServiceStack.Razor.ViewPage">
<namespaces>
<add namespace="ServiceStack.Html" />
<add namespace="ServiceStack.Razor" />
<add namespace="ServiceStack.Text" />
<add namespace="ServiceStack.OrmLite" />
<add namespace="Concrete_Assembly" />
<add namespace="Common_Assembly" />
</namespaces>
</pages>
</system.web.webPages.razor>
Also disable ASP.NET webpages:
<appSettings>
<add key="webPages:Enabled" value="false" />
</appSettings>
See the RazorRockstars Self Host app.config for a reference.

Using MVC HtmlHelper extension method in a View within an Area

I have an HtmlHelper extension method that pulls in localized text from a database cache. The code is like this. (MVCWeb is the namespace of my MVC app.)
using System.Web;
using System.Web.Mvc;
namespace MVCWeb.PresentationExtensions
{
public static class HtmlHelperExtensions
{
public static HtmlString GetText(this HtmlHelper Html, string keyword)
{
// code to get the text based on the keyword
}
}
}
I am using #using MVCWeb.PresentationExtensions in my Views. In ~/Views folder, calling the extension method is working perfectly.
I recently added an Area. I am using the extension method in the View files in the ~/Areas/AreaName/Views folder, and the code is compiling and it does work, however I am getting errors in the IDE.
Every time I use #Html.GetText("SomeKeyword") from within the Area view, the following two errors are displayed on the errors list.
'System.Web.WebPages.Html.HtmlHelper' does not contain a definition for 'GetText' and the best extension method overload 'MVCWeb.PresenationExtension.HtmlHelperExtensions.GetText(System.Web.Mvc.HtmlHelper, string)' has some invalid arguments
Instance argument: cannot convert from 'System.Web.WebPages.Html.HtmlHelper' to 'System.Web.Mvc.HtmlHelper'
I've figured out that in ~/Views, #Html has the following code comments:
HtmlHelper<dynamic> WebViewPage<dynamic>.Html
Gets or sets the System.Web.Mvc.HtmlHelper object that is used to render HTML elements.
In ~/Area/AreaName/Views, #Html has these comments:
HtmlHelper WebPage.Html
Gets the System.Web.WebPages.Html.HtmlHelper object that is associated with a page.
For reference, my Web.config files in ~/Views and ~/Areas/AreaName/Views match. This is an MVC4 app on .NET 4.5 and hasn't been converted from a previous version of MVC.
Is it normal that #Html is defined as different types in the regular Views vs area Views?
Why is this compiling and running correctly if the IDE is showing errors? Is this an IDE bug?
How can I stop these errors from showing in the IDE?
it runs fine because your web.config contains the correct reference and it matches up at runtime correctly.
it's just an ide bug for areas. To get rid of it you can specify it as an include at the top of your view using #include which will give intellisense a helping hand.
I've just run into the same issue trying to add an MvcSiteMap helper to a View in an Area.
The problem was that the NuGet package added its namespaces to the Web.Config files at the root and Views level but unsurprisingly wasn't smart enough to go looking for the ones buried in the Areas/area_name/Views folders. The solution was just to add the namespaces e.g.
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.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.Optimization" />
<add namespace="System.Web.Routing" />
<add namespace="FarmingtonCo.CacPortalWeb" />
<add namespace="MvcSiteMapProvider.Web.Html" />
<add namespace="MvcSiteMapProvider.Web.Html.Models" />
</namespaces>
</pages>

Categories

Resources