So i've been working on a MVC2 application just to learn the ropes really. One thing i did not like about the default set-up is that the views, models and controllers were in a single assembly together. This was not hard to overcome, moved both to different projects and migrated each folders contents over.
However, now time has come to start fiddling with user roles. I decorate a controller action like so;
[Authorize(Roles = "Admin"), AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditProject(Guid Id, FormCollection formValues){}
So here is how my solution is setup;
MySolution.Web.Views <-- All aspx /
ascx stuff
MySolution.Controllers
<-- All controllers, including the
default AccountController that comes
with the MVC2 application
I also have the default 'AccountModel' within the MySolution.Controllers.AccountModels namespace which is where the LogOnModel class is located. Now when i run the program and ask the controller to execute an action which requires a certain role (which i am not) I get the following error;
"Compiler Error Message: CS0234: The type or namespace name 'Models' does not exist in the namespace 'MySolution.Web' (are you missing an assembly reference?)"
It also highlights the following line as the source error;
"public class views_account_logon_aspx : System.Web.Mvc.ViewPage, System.Web.SessionState.IRequiresSessionState, System.Web.IHttpHandler"
and comments the line and file of the error as;
"Source File: c:\Users\\AppData\Local\Temp\Temporary ASP.NET Files\root\d1b48054\1ce7c091\App_Web_logon.aspx.5f83eb8c.mdfplvvy.0.cs"
So I have tried navigating to that file and manually typing in the correct namespace of the LogOnModel but each time i run the project, a new version of this file is created with the incorrect location of LogOnModel reproduced. So clearly there is something within the application that is still looking in the original location for the AccountModel which no longer exists.
I have looked in my web.config file and cannot find anywhere which appears to reference the LogOnModel in the MySolution.Web namespace.
Does anyone know how I might inform the application where the LogOnModel now resides ?
The actual application is failing within the AccountController's LogOn action:
public ActionResult LogOn()
{
return View(); // Failing here
}
So maybe it's something to do with routing ? I have not touched the default setup of the Global.asax file.
Have you referenced MySolution.Controllers.AccountModels in your web.config namespace section? Or use the Import directive in your aspx, or give the full name in the page directive ViewPage<MySolution.Controllers.AccountModels.LogOnModel>
Related
I have been writing ASP.NET MVC for more then 10 years. I always know there is a convention for the Controller class must have it's name suffix with Controller. As I know, it's a hard limit on ASP.NET MVC 5 and before.
One day I saw one of my colleague write a controller in ASP.NET Core 6 like this:
using Microsoft.AspNetCore.Mvc;
namespace WebApplication2.Controllers;
public class Home : Controller
{
private readonly ILogger<Home> _logger;
public Home(ILogger<Home> logger)
{
_logger = logger;
}
public IActionResult Index()
{
return View();
}
}
I shocked. I can't believe there is someone would write Controller code like this. Then I see this:
A controller is an instantiable class, usually public, in which at least one of the following conditions is true:
The class name is suffixed with Controller.
The class inherits from a class whose name is suffixed with Controller.
The [Controller] attribute is applied to the class.
Then I know the Controller suffix is not a MUST. It's just a recommended naming rule. Without Controller-suffix, it might come with come drawback like this. I also found this post. I always believe naming controller with -Controller suffix is a good practices. I just want to know that if anyone know why ASP.NET Core teams decided not have to be naming controllers with Controller suffix?
why the hard limit had been removed
I think the reason may as below:
From this answer we see
By not having the controller naming convention, we'd have two types
with the same name hence would always have to provide namespaces to
distinguish between the two. But because we do have this convention
this is not necessary and no type clashes occur.
By having Controller suffix on controller types, this is not necessary.
In ASP.NET Core the namespace of the controller class is unimportant, although the tradition is maintained by tooling that continues to place controller classes always under a folder named Controllers. In fact, you can now place your controller classes in any folders and any namespaces that you wish. As long as at least one of the following conditions is true.
Besides,controllers need no Controller type name appending because after all they're just like any other class.It is a form of optimization that reduces overhead and the memory footprint.
I am using ASP.NET MVC 5.2.6 on .NET framework version 4.5.2.
I have an area named Admin in which I have the following:
namespace MyCode.Controllers
{
[RoutePrefix("admin/article")]
public class ArticleController : Controller
{
[Route("new")]
public ActionResult New()
{
return View();
}
}
}
I also have a view named New.cshtml in the Admin area's Views\Article folder.
Areas\Admin\Views\Article\New.cshtml
However, when I run my application, MVC is only looking in the Views folder within my area-less root. From my past experience, it starts to look in the Views folder within the area.
Is it because the new attribute based routing that MVC doesn't know that I am inside the Admin area?
I know I could and I don't want to be providing the full path to each view because that's a pain in the neck. My question isn't, where do I go from here now? It is, as the title says, the following:
Is there a way to tell it to look for views in the area first?
Holy smokes!
I finally found out the solution to my problem. Here's what you must do if you face this problem.
Make sure that the controllers in your areas reside in a namespace different from the namespace of the controllers in your area-less root. This should be so even if the controller names are unique. It doesn't matter that you use attribute routing or not.
So, if you have an area-less root like so:
Root
namespace MyCode.Controllers
{
public class HomeController : Controller
{
}
}
Foo Area
namespace MyCode.Controllers
{
[RoutePrefix("whatever/it/doesnt/matter")]
public class FooController : Controller
{
}
}
You will have the same problem. Change it like the following so that the controllers of the area reside in a namespace separate from that of the root, and the problem will go away.
Foo Area
namespace MyCode.Areas.Foo.Controllers // or anything else other
// than the namespace where root controllers are
{
[RoutePrefix("whatever/it/doesnt/matter")]
public class FooController : Controller
{
}
}
This is most likely a bug in the ASP.NET MVC source.
PS:
Even RouteDebugger told me there wasn't a problem with my route and it was able to resolve my path localhost:<port>/Admin/Article/New to the correct controller and action, yet ASP.NET MVC couldn't resolve my controller and action and reported a 404.
This deleted answer from #lawphotog has a link to a video that helped me solve my problem.
This is really weird. As it sounds, I have tried to create a project/solution named MvcApplication using Visual Studio 2015 (Enterprise). I choose MVC template and leave all default as it is.
It created successfully. I build solution without any errors or warnings. When I run the project (start debugging) it loads ASP.NET MVC home page, which is fine.
enter image description here
When I click Register immediately throws an error CS0426: The type name Models does not exist in the type MvcApplication.
in source file some where in temp folder. (Screenshot attached).
enter image description here
So far I tried to solve this problem using following
1. Close solution and restart machine. (did not work)
2. Delete all temporary file (did not work)
3. Create other application with different name (worked)
4. Add new project in above solution with same name 'MvcApplication' (same issue - did not work, but it proves that there is an issue with name MvcApplication.)
5. Google it (Not much help regarding CS0426 error) - It does not make any sense. (Why?)
6. MSDN, StackOverflow, other blogging reported error but not cause or solution? still puzzled why?
I wish I could be help but I need to confirm that you can not name your project 'MvcApplication' in your solution and expect to work. I could be wrong. But I need more proof in this case.
Any help will be greatly appreciated.
Thanks.
Assume Register view has this model binding:
#* Register view *#
#model MvcApplication.Models.RegisterViewModel
Since you have MvcApplication as project/solution name (including project namespace), it is possible to have naming conflict with MvcApplication class that already provided in Global.asax when defining view model:
// Global.asax
namespace MvcApplication
{
public class MvcApplication : System.Web.HttpApplication
{
// other stuffs here
}
}
// Model class
namespace MvcApplication.Models // ==> potential naming collision when being used in view
{
public class RegisterViewModel
{
// some properties here
}
}
To avoid collision with MvcApplication class shown like above, you can use global with fully qualified name like this one in view page:
#model global::MvcApplication.Models.RegisterViewModel
or simply changing project namespace into different name.
Similar issue:
The type name 'Models' does not exist in the type 'System.Web.Helpers.Chart'
I am a long-time semi-professional asp.net programmer who has recently made the leap from asp.net forms environment to MVC. So I am in the process of re-developing one of my web apps which exists in forms to MVC, and I am really liking the MVC environment and am glad I am making the leap.
But...am encountering some issues, like this one with namespaces.
So let's imagine the following:
1) I create a new MVC 4 project called MyMvcProject
2) I immediately create the App_Code folder and add to it a new class1.vb file as follows:
Namespace MyNamespace
Public Class Class1
Property MyProperty As String
End Class
End Namespace
Ok so far so good. Now I want to access this class in a controller or something as follows:
Imports MyNamespace
Public Class Default1Controller
Inherits System.Web.Mvc.Controller
Function Index() As ActionResult
Dim obj As New Class1
Return View()
End Function
End Class
In the asp.net forms environment, I would be good to go. However, in my MVC project i am unable to import "MyNamespace" and therefore unable to create Class1. So I go looking for it and find the following in the object browser:
>[OTHER REFERENCES...]
v[VB] MyMvcProject
>{}MyMvcProject
>{}MyMvcProject.My
>{}MyMvcProject.My.Resources
v[VB] MyMvcProject
v{}MyNamespace
> [] Class1
>[OTHER REFERENCES...]
So there's my "MyNamespace" and "Class1." So I attempt to revise the code as follows:
Imports MyMvcProject.MyNamespace
Public Class Default1Controller
Inherits System.Web.Mvc.Controller
Function Index() As ActionResult
Dim obj As New Class1
Return View()
End Function
End Class
But THIS doesn't help. I am only able to reference the FIRST instance MyMvcProject and it's sub-references. Not the second where my "Class1" resides. I am uncertain as to how to fix this.
UPDATE 1: I FOUND THE SOLUTION (BUT NOT THE EXPLANATION)
For whatever reason, ASP.NET MVC does not like me to put stuff in the App_Code folder. However, if i put the class1.vb in the MODELS folder then I can I can import "MyMvcProject.MyNamespace" and proceed normally. The object browswer now looks like this:
>[OTHER REFERENCES...]
v[VB] MyMvcProject
>{}MyMvcProject
>{}MyMvcProject.My
>{}MyMvcProject.My.Resources
v{}MyMvcProject.MyNamespace
> [] Class1
v[VB] MyMvcProject
>[OTHER REFERENCES...]
Notice the second reference to MyMvcProject STILL exists. But "MyNamespace" and the classes i put into it are under the FIRST instance, which I can reference and import normally. Kind of quirky, it seems to me. But if i have to throw everything in the MODELS folder, well, I'll do it.
UPDATE 2
Had I know the problem was with putting stuff in the App_Code folder, I could have found some answers:
ASP.NET MVC using App_Code directory
UPDATE 3
All MVC project by default are Web Application Projects (WAP) instead of Web Site projects. This means that there's no need for an App_Code folder since WAPs always get compiled anyway. That means that all *.cs files in your project will get compiled, as opposed to Web Site projects where only *.cs files in your App_Code folder would get compiled.
Source: http://forums.asp.net/t/1315143.aspx?MVC+and+App_Code+folder
UPDATE 4
And here is how to include the App_Code folder in your MVC project:
you have to go at Properties section of the file and then for Build Action change from Content to Compile. That is it ;)
Source: http://how-to-code-net.blogspot.mx/2014/04/appcode-classes-not-available-in-aspnet.html
I'm trying to build some .ascx controls into a class library for plugins for a CMS I'm building.
My project type is a typical C# class libary with references added for system.web.mvc & friends.
My problem arises in trying to create a strongly-typed user control. My control looks like this:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<TagCloudWidget.Models.TagCloudWidgetData>" %>
Even though I have another public class in the same project under the namespace TagCloudWidget.Models, I can't seem to get the .ascx file to recognize this. I've tried including Imports for the namespace, but then it just complains that the namespace doesn't exist. The TagCloudData class file looks like this:
namespace TagCloudWidget.Models
{
public class TagCloudWidgetData
{
public IList<TagCount> TagCounts { get; set; }
public ContentTypes ContentType;
public string Controller;
public string Action;
public TagCloudWidgetData(IList<TagCount> tagCounts, ContentTypes contentType, string controller, string action)
{
TagCounts = tagCounts;
ContentType = contentType;
Controller = controller;
Action = action;
}
}
}
Can you see what I'm doing wrong?
Since the suggestion below, I've tried adding a code-behind file. I think I'm closer to figuring out what's wrong, but I'm still not able to find a solution. In the project, I've added references to System.Web and System.Web.Mvc. But, in the using section of the codebehind file, when I type "using System.", auto-complete doesn't even show System.Web or System.Web.Mvc as available options. It's like they just don't exist on disc. Other projects are able to include them and reference them just fine. I suppose this is the source of my problem, so I'm hopeful once I figure this out the rest will just fall into place. Ideas?
I've had similar problems with an application that I started with the beta release. The only thing I've found that works is to create a code-behind file for the control and define the inheritance in the code-behind. Then in the control, have it inherit from the class defined in your code-behind. In newer projects, built from scratch using 1.0, I don't have this problem -- but then again I don't have my partial classes defined in a library, either.
Success! Somehow, my .ascx file had been marked "content" in the file properties instead of "compile". Once I fixed that, I can now reference the necessary assemblies and load/run the plugin without problems. Thanks for the tip on the codebehind file!
(update) The other tip I figured out last night is that my plugin also has to be in the app's /bin directory as well as my /widgets directory, otherwise I get a "Could not load type..." exception. I haven't figured out yet how to wire up ASP.NET MVC so I only have to have it in 1 place, but when I do, I'll post back here.