How to build ASP.NET MVC user controls into class libraries - asp.net-mvc

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.

Related

Why am I getting CS0426 error when I give project name 'MvcApplication' using ASP.Net?

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'

Namespace conflicts in Asp.net MVC

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

How to read ConnectionString from web.config in Asp.net MVC3 web Application?

I am working in Asp.net Razor MVC3. I have created a App_Code folder and make a class in which I want read connection string from web.config and working with database by using this class. I am writing System.Configuration in this app_code class but it didn't shows me ConfigurationManager of Configuration class.
It shows like this
Rather than if I am write the same line in any controller then it will show System.Configuration.ConfigurationManager and in controller I can read connection string from web.config but in app_code I can't.
Please give me the solution how to read connection string in app_code class?
Include a reference to System.Web.Configuration:
using System.Web.Configuration;
Then, in your code, access it like this:
WebConfigurationManager.ConnectionStrings["ConnectionStringName"].ConnectionString;
Example Class:
using System.Web.Configuration;
namespace MyWebApp.App_Code
{
public class TestClass
{
public void TestMethod()
{
var connStr = WebConfigurationManager.ConnectionStrings["ConnectionStringName"].ConnectionString;
}
}
}
If you receive an error regarding "the ConfigurationManager does not exist in the current context", you will need to install the dll assembly besides for having the using System.Configuration statement in your controller.
You can find that in the Nuget gallery here https://www.nuget.org/packages/System.Configuration.ConfigurationManager/ or by added an assembly reference inside Visual Studio.
After that, you can write string MyString = ConfigurationManager.ConnectionStrings["ConnectionStringName"].ConnectionString; (notice the singular form at the end of that piece of code).
Or if you haven't written the using statement for System.Configuration you will write the same thing but preface it with string MyString = System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionStringName"].ConnectionString;

MVC2 LogOnModel not found

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>

AuthorizeAttribute extension for .net MVC...two problems/questions

my first question is, where do I put this custom extension so that it can be called rather than the default AuthorizeAttribute?
I currently have created a new project that contains all of my business logic within my MVC solution. I have a .cs file within my logic project that contains all of my security classes. I tried adding an extension class to that file and on my controller, it sees the class just fine and intellisense isn't barking at me when I add the attribute, but when I try to compile, I get an error that the type or namespace could not be found. Does the custom attribute need to be housed somewhere special in order to compile?
Second question...could be related to the first: When I'm trying to override the AuthorizeCore method from AuthorizeAttribute, I'm passing in System.Web.HttpContextBase as httpcontext. For some reason visual studio can't resolve System.Web.HttpContextBase. Again this might be related to where I have this class saved in my solution. Or perhaps I need to import a dll somewhere to extend this?
Please advise.
As far as I am aware the class can be in any class library project as long as you have properly referenced the project in your web site. You might want to try recompiling the project -- it sounds like it's able to find the source files, but the code isn't in the DLL.
You probably need to add in a reference to System.Web.Abstractions to your project. While the "base" classes are in the System.Web namespace, they are found in a different DLL.
It works for me,I hope this will help you.
using System.Web.Mvc;
public class CustomAuthorize : AuthorizeAttribute
{
}
In controller
[CustomAuthorize]
public class OrderController : Controller
{
}

Resources