Custon Razor HtmlHelper conflicts with namespace at runtime - c#

I have created a custom WebViewPage. That allows me to add a custom helper to the use in my Razor views:
public abstract class CompanyNameWebViewPage<TModel> : WebViewPage<TModel>
{
public override void InitHelpers()
{
base.InitHelpers();
CompanyName = new CompanyNameHtmlHelper<TModel>(this.Html);
}
public CompanyNameHtmlHelper<TModel> CompanyName { get; protected set; }
}
Using it in my Razor as such:
#CompanyName.Theme.Image("logo.png")
The problem is that CompanyName is both the name I really want to use for the HTML helper and the namespace our code goes in. So, in visual studio #CompanyName.Theme.etc resolves to my CompanyNameHtmlHelper.
However, at runtime I get the error:
The type or namespace name 'Theme' does not exist in the namespace 'CompanyName' (are you missing an assembly reference?)
From which it is obvious that CompanyName is now resolving to the namespace instead of the HtmlHelper.
Why does this happen? Why does Visual Studio allow me to do this when it's going to give me a runtime error? Are there any work arounds? It's really annoying to have to come up with some convoluted name instead of just the name of my company.

Related

Mysterious name resolution differences between legacy and SDK-style C# projects

I encountered this confusing names-resolution problem while trying to convert legacy solution with .NET 4.6.1 projects to the new SDK-style project formats. I was able to create a minimal repro solution LegacyVsSdkStyleProjectNameResolution, which is on GitHub here:
https://github.com/PaloMraz/LegacyVsSdkStyleProjectNameResolution.git
The solution contains:
3 legacy projects targeting .NET Framework 4.6.1 residing in the „Legacy“ solution folder; the project names start with „Legacy.“).
3 SDK-style projects targeting .NET residing in the „Sdk“ solution folder; the project names start with „Sdk.“.
(Please forgive me the non-intuitive assembly / namespace / class names – I could not use the original names and was not able to devise something more feasible).
The dependencies are shown in this image:
The problem is, the Legacy.Common.Configuration project successfuly compiles with this Bundle class declaration:
using Legacy.Common.Data;
namespace Legacy.Common.Configuration
{
public class Bundle
{
public Person Person { get; set; }
}
}
But the Sdk.Common.Configuration produces compilation error CS0118 ('Person' is a namespace but is used like a type):
using Sdk.Common.Data;
namespace Sdk.Common.Configuration
{
public class Bundle
{
public Person Person { get; set; }
}
}
Can anybody please explain, why the C# compiler in the Sdk.Common.Configuration project resolves the Person type symbol incorrectly to namespace Sdk.Common.Person, but in the Legacy.Common.Configuration it resolves it correctly to Legacy.Common.Data.Person class?
In SDK-style projects, a project will automatically inherit all of the things that its dependencies depend on. In legacy projects this had to be done manually, with the tooling inserting explicit references to all of the things that a new dependency depended on.
So in your SDK-style project, Sdk.Common.Configuration is inheriting a reference to Sdk.Common.Person.Management, by virtue of the fact that it references Sdk.Common.Data.
Sdk.Common.Person.Management defines the namespace Sdk.Common.Person:
namespace Sdk.Common.Person.Management
{
...
}
While Sdk.Common.Data defines the class Sdk.Common.Data.Person.:
namespace Sdk.Common.Data
{
public class Person
{
}
}
Sdk.Common.Configuration then does this:
using Sdk.Common.Data;
namespace Sdk.Common.Configuration
{
public class Bundle
{
public Person Person { get; set; }
}
}
There, the compiler searches the namespace Sdk.Common.Configuration (and Sdk.Common, and Sdk) for Person before it considers that using. It finds Sdk.Common.Person which is a namespace, and complains because you're using a namespace as a type.
If you include the using inside the namespace, this order flips, and the compiler will search Sdk.Common.Data first, and find the Sdk.Common.Data.Person class:
namespace Sdk.Common.Configuration
{
using Sdk.Common.Data;
public class Bundle
{
public Person Person { get; set; }
}
}
See this answer for details.
As for how to solve this, first off don't define a class and a namespace with the same name. If you can't avoid this, you can either change the location of the using as shown above, or use the fully-qualified name of the Person class.
If you want to mirror the legacy behaviour of Sdk.Common.Data's references not being inherited by Sdk.Common.Configuration, use PrivateAsserts="All" on the ProjectReference which includes Sdk.Common.Person.Management.
<ProjectReference Include="..\Sdk.Common.Person.Management\Sdk.Common.Person.Management.csproj" PrivateAssets="All" />
This states that Sdk.Common.Person.Management is a private dependency, which isn't inherited by anything which references Sdk.Common.Data.

Nunit Test. Visual Studio. Namespace , class issue

.I m very new to programming, and I think I'm loosing my mind trying to understand what's the problem here. Does Anyone have any suggestions?
The Test Project has Reference set to OrderManagementSystem.Domain and OrderManagementSystem.Controllers.
The Controllers Class is Public .
Im able to access Classes from Domain Namespace , but not Controllers??
What did i do wrong?
This error is because your class name is Controllers and namespace also contains .Controllers.
Either update the name of class or remove .Controllers from the namespace OrderManagementSystem.Controllers
In Controllers.cs file,
using Systems;
....
//Remove .Controllers from namespace
namespace OrderManagementSystems
{
public class Controllers
{
//Your code
}
}

Referencing classes in a Razor Class Library

I created a new Razor Class Library (using "dotnet new razorclasslib"). I then created a folder called Models in the new library and it contains a class with the following test code:
using System;
namespace TestLibrary.Models
{
public class TestModel
{
public string TestMethod { get; set; }
}
}
However, when I try to use this class from the web application project (by referring to it as TestLibrary.Models.TestModel) I keep being told that the TestLibrary.Models namespace doesn't exist. The exact error is:
The type or namespace name 'Models' does not exist in the namespace 'TestLibrary' (are you missing an assembly reference?) [TestApplication]
I'm assuming I'm missing something simple, just can't figure out what.
This issue was somehow related to the issue posted here: Razor Class Library MSBuild MSB4062 Error During Compile. Once that was resolved this issue went away.

Namespace not found error when compiling assembly from files

What I'm trying to achieve is generate a project dynamically from c# classes generated by me.
This classes' content are a similar content of code-first code generation of entity framework.The content looks as follows:
namespace ElasticTables
{
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations.KeyAttribute;
[Table("address")]
public partial class address
{
[Key]
public decimal id { get; set; }
public string name { get; set; }
}
}
I generate this files from the tables in my database, and then try to compile it programmatically so that I can reference the generated project in another project that works with an API.
The main errors while compiling is:
The type or namespace name 'KeyAttribute' does not exist in the namespace 'System.ComponentModel.DataAnnotations' (are you missing an assembly reference?)
The type or namespace 'Key' could not be found
The type or namespace 'Table' could not be found.
I'm using 'CSharpCodeProvider'
var provider = new CSharpCodeProvider();
var options = new CompilerParameters
{
OutputAssembly = "ElasticTables.dll",
CompilerOptions = "/optimize"
};
And I have the following referenced Assemblies
options.ReferencedAssemblies.Add(Directory.GetCurrentDirectory() + "\\EntityFramework.dll");
options.ReferencedAssemblies.Add(Directory.GetCurrentDirectory() + "\\EntityFramework.SqlServer.dll");
I have an string array with the files' paths called sources, and I try to compile with the following line
CompilerResults results = provider.CompileAssemblyFromFile(options, sources);
Help is much appreciated.
You need to reference all needed assemblies (as the error says), so you need to add, I'd say at the very least:
options.ReferencedAssemblies.Add("System.dll");
options.ReferencedAssemblies.Add("System.ComponentModel.DataAnnotations.dll");
Others might be needed
About the comment in your question, yes, you should specify options.OutputAssembly
Also, in your generated code:
using System.ComponentModel.DataAnnotations.KeyAttribute;
KeyAttribute is not a namespace, so it'll probably give an error when compiling.
I'd also take the usings before the namespace. This is not strictly needed and not an error, but it's the common practice (and that way you are sure the referenced assemblies are from the global namespace, and not childs of the namespace your class is in [just in case there's a name conflict])
Have you tried to add also a reference to "System.dll" and "System.ComponentModel.DataAnnotations.dll" (for the System.ComponentModel stuff) ?
(as you may indeed be missing an assembly reference)
options.ReferencedAssemblies.Add(
Path.Combine(
Directory.GetCurrentDirectory(),
"System.ComponentModel.DataAnnotations.dll"));

Using a class library variable in an aspx page

I have the following object in a class library:
namespace ID.CentralisedObjects
{
public class Details
{
public string ContactName { get; set; }
}
}
in the aspx page in my website project (which has a reference to the class library), I am trying to print out the ContactName by using code along the lines of
<div><%= ID.CentralisedObjects.Details.ContactName %></div>
However, it is thinking that the ID at the start of this is Page.ID so it isn't finding my object properly. How do I make it look for the class library ID?
standard naming of namespace has enough influence on your application, changing it according to the naming namespaces guidelines will solve your problem
http://msdn.microsoft.com/en-us/library/893ke618(v=vs.71).aspx
For the namespace conflict: use a qualifier
using DrawCharts IDS = ID;
IDS.CentralisedObjects.Details.ContactName
The other mentioned problems are unresolved by this solution.

Categories

Resources