Ninject in ASP.NET MVC4 - c#

So after much screwing around I finally got Ninject wired in and compiling in my MVC4 application. The problem I was running into is the IDependencyScope interface no longer exists from what I can tell and the System.Web.Http.Dependencies namespace was done away with.
So, my problem now is I have everything wired in and upon running the application I get:
Sequence contains no elements
[InvalidOperationException: Sequence contains no elements]
System.Linq.Enumerable.Single(IEnumerable`1 source) +379
Ninject.Web.Mvc.NinjectMvcHttpApplicationPlugin.Start() in c:\Projects\Ninject\ninject.web.mvc\mvc3\src\Ninject.Web.Mvc\NinjectMvcHttpApplicationPlugin.cs:53
Ninject.Web.Common.Bootstrapper.<Initialize>b__0(INinjectHttpApplicationPlugin c) in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\Bootstrapper.cs:52
Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map(IEnumerable`1 series, Action`1 action) in c:\Projects\Ninject\ninject\src\Ninject\Infrastructure\Language\ExtensionsForIEnumerableOfT.cs:31
Ninject.Web.Common.Bootstrapper.Initialize(Func`1 createKernelCallback) in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\Bootstrapper.cs:53
Ninject.Web.Common.NinjectHttpApplication.Application_Start() in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\NinjectHttpApplication.cs:81
Which I haven't been able to track down or even begin to fathom where it is coming from.
My standard Ninject methods inside the Global.asax.cs look as follows:
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind<IRenderHelper>().To<RenderHelper>();
GlobalConfiguration.Configuration.ServiceResolver.SetResolver(new NinjectDependencyResolver(kernel));
return kernel;
}
protected override void OnApplicationStarted()
{
base.OnApplicationStarted();
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
BundleTable.Bundles.RegisterTemplateBundles();
}
And my custom resolver:
public class NinjectDependencyResolver : IDependencyResolver
{
private readonly IKernel _kernel;
public NinjectDependencyResolver(IKernel kernel)
{
_kernel = kernel;
}
public object GetService(Type serviceType)
{
return _kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return _kernel.GetAll(serviceType);
}
catch (Exception)
{
return new List<object>();
}
}
public void Dispose()
{
// When BeginScope returns 'this', the Dispose method must be a no-op.
}
}
Any insight here would be greatly appreciated. I've spent far too much time already trying to get any DI framework wired into the latest MVC4 RC running on .NET 4.5 and have now just reached my tolerance level for things just not working at all..
Edit #1
A little further research digging around in github the ExtensionsForIEnumerableOfT.cs doesn't help much:
https://github.com/ninject/ninject/blob/master/src/Ninject/Infrastructure/Language/ExtensionsForIEnumerableOfT.cs
And possibly if I had wrote it myself I would begin to understand this but Bootstrapper.cs doesn't help too much either.
https://github.com/ninject/Ninject.Web.Common/blob/master/src/Ninject.Web.Common/Bootstrapper.cs
Hoping these details will make it easier for any of you who might have more experience with Ninject.
Edit #2 The error encountered is specifically in NinjectMvcHttpApplicationPlugin.cs:
The offending line is:
ModelValidatorProviders.Providers.Remove(ModelValidatorProviders.Providers.OfType<DataAnnotationsModelValidatorProvider>().Single());
Which lives in the following method:
public void Start()
{
ModelValidatorProviders.Providers.Remove(ModelValidatorProviders.Providers.OfType<DataAnnotationsModelValidatorProvider>().Single());
DependencyResolver.SetResolver(this.CreateDependencyResolver());
RemoveDefaultAttributeFilterProvider();
}
The ModelValidatorProviders collection contains 2 elements:
{System.Web.Mvc.DataErrorInfoModelValidatorProvider}
{System.Web.Mvc.ClientDataTypeModelValidatorProvider}
And it's trying to remove a single instance of:
System.Web.Mvc.DataAnnotationsModelValidatorProvider
Which apparently isn't loaded up in the ModelValidationProviders.Providers collection. Any ideas from here?
Resolution to Above Exception And Onto The Next
To resolve the issue in the ModelValidatorProviders I had to manually add an object it was expecting. So now my CreateKernel method looks like:
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
kernel.Bind<IRenderHelper>().To<RenderHelper>();
kernel.Unbind<IDocumentViewerAdapter>();
GlobalConfiguration.Configuration.ServiceResolver.SetResolver(new NinjectDependencyResolver(kernel));
ModelValidatorProviders.Providers.Add(new DataAnnotationsModelValidatorProvider());
FilterProviders.Providers.Add(new FilterAttributeFilterProvider());
return kernel;
}
Now it runs and gets into the actual guts of Ninject but still has an issue, one that makes no sense yet again:
Exception Details: Ninject.ActivationException: Error activating IntPtr
No matching bindings are available, and the type is not self-bindable.
Activation path:
3) Injection of dependency IntPtr into parameter method of constructor of type Func{IKernel}
2) Injection of dependency Func{IKernel} into parameter lazyKernel of constructor of type HttpApplicationInitializationHttpModule
1) Request for IHttpModule
Suggestions:
1) Ensure that you have defined a binding for IntPtr.
2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
3) Ensure you have not accidentally created more than one kernel.
4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
5) If you are using automatic module loading, ensure the search path and filters are correct.

Ok after beating my head against the wall for far too long I figured out what was going on. The default project type for MVC4 running on .NET 4.5 had a reference to the original RC version of System.Web.Http instead of the updated version.
Namespaces were missing, objects didn't exist, life was not good.
Steps for resolution:
Remove your reference to System.Web.Http in your MVC4 project
Add Reference -> System.Web.Http
Delete all work arounds you put in to get the old garbage version of System.Web.Http to work
Reapply standard process to wire in Ninject.
HOWEVER, the error of:
Exception Details: Ninject.ActivationException: Error activating IntPtr
No matching bindings are available, and the type is not self-bindable.
Activation path:
3) Injection of dependency IntPtr into parameter method of constructor of type Func{IKernel}
2) Injection of dependency Func{IKernel} into parameter lazyKernel of constructor of type HttpApplicationInitializationHttpModule
1) Request for IHttpModule
Suggestions:
1) Ensure that you have defined a binding for IntPtr.
2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
3) Ensure you have not accidentally created more than one kernel.
4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.
5) If you are using automatic module loading, ensure the search path and filters are correct.
Update This was solved by updating MVC from MVC4 Beta to MVC4 RC.

Check out the Pro ASP.NET MVC 3 book. I just ported this code over from MVC3 to MVC4 last night and works correctly. Page 322 to be exact.
What I don't see is where you are mapping your Interface to your concrete items.
Bind<ISomething>().To<Something>();
Add another constructor and add the method that calls your mapping;
public NinjectDependencyResolver() {
_kernal = new StandardKernel();
RegisterServices(_kernel);
}
public static void RegisterServices(IKernel kernel) {
kernel.Bind<ISomething>().To<Something>();
}
Here's what a resolver could/should look like;
public class NinjectDependencyResolver : IDependencyResolver {
private IKernal _kernel;
public NinjectDependencyResolver(){
_kernal = StandardKernal();
AddBindings();
}
public NinjectDependencyResolver(IKernel kernel)
{
_kernel = kernel;
}
public object GetService(Type serviceType)
{
return _kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return _kernal.GetAll(serviceType);
}
public IBindingToSyntax<T> Bind<T>() {
return _kernal.Bind<T>();
}
public static void RegisterServices(IKernel kernel){
//Add your bindings here.
//This is static as you can use it for WebApi by passing it the IKernel
}
}
Global.Asx -
Application_Start()
method
DependencyResolver.SetResolver(new NinjectDependencyResolver());
That's it.
UPDATED 11/14/2012
On a side note, if you're working with MVC WebAPI, you will want to use WebApiContrib.IoC.Ninject from nuget. Also, check out the "Contact Manager" in their samples asp.net.com. This helped to cleanup the implementation of Ninject

Just delete NinjectWebCommon.cs file from your project (it is in App_Start folder). and everything should be working.
Source: http://mlindev.blogspot.com.au/2012/09/how-to-implement-dependency-injection.html

When you will install latest Ninject.MVC3 from NuGet package we find following code on top of the NinjectWebCommon.cs file:
[assembly: WebActivator.PreApplicationStartMethod(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(MvcApplication1.App_Start.NinjectWebCommon), "Stop")]
in this case we dont need to register ninject explicitly in global.asax
I found a good content on using Ninject with MVC 4 here

I tend to keep my Ninject bootstrapping in a separate project. In order to use the .InRequestScope() extension method of IBindingInSyntax<T>, I had added via Nuget the Ninject.Web.Common library. Alas, this library includes the app_start bootstrapper, resulting in duplicate NinjectWebCommon classes and attachment via WebActivator (1 in said project and 1 in the MVC project itself).
I deleted the duplicate App_Start folder from my bootstrap project, and this solved it.

I have come across the same issue not quite sure what has fixed after below changes
added Ninject.MVC4 to project
deleted NinjectWebCommon.cs (the generated file, as the integration already exists in global.ascx.cs file)

I am using DD4T, and encountered same error.
After confirming that all packages are installed by nuget package manager,
I found that some of the DLLs/references were missing (newtonsoft etc):
Then, after re-installing Newtonsoft.Json (to re-install package use following command in Nuget Package Manager:Update-Package –reinstall Newtonsoft.Json), and putting netrtsn.dll from Tridion Deployer bin, I got this error - "Sequence contains no elements" with exactly same stack trace as given in this question.
Thanks to Naga, for providing this resolution
deleted NinjectWebCommon.cs (the generated file, as the integration already exists in global.ascx.cs file), and wohooooo!!!! all errors resolved, Tridion + MVC4 = DD4T is running fine now.

I have also had this problem when I used nuget to install Ninject.MVC4 in a project referenced by my actual MVC website project.
The trouble is that the NinjectWebCommon.cs file automatically installed in the App_Start directory of the referenced project conflicts with the (actual, useful) one installed in my website project. Removing the NinjectWebCommon.cs file from the referenced project resolves the error.

Related

calling AddAutoMapper once per assembly instead of passing in multiple assemblies?

I have a multi layered project with a web API project and a library project. Both projects rely on AutoMapper (and AutoMapper extensions for Microsoft.Extensions.DependencyInjection). Based on this
https://docs.automapper.org/en/latest/Dependency-injection.html#asp-net-core
in the Startup file I'm setting up AutoMapper for all the layers
Assembly apiAssembly = Assembly.GetExecutingAssembly();
Assembly myLibraryAssembly = Assembly.Load("MyLibrary");
services.AddAutoMapper(apiAssembly, myLibraryAssembly);
As you can see here, the API project needs to know about all the referenced library projects by loading them via name. I would prefer a way that every project is able to register itself. Based on this sample code
https://github.com/jasontaylordev/CleanArchitecture/blob/master/src/Application/DependencyInjection.cs
I created such a file in my library project
public static class DependencyInjection
{
public static IServiceCollection AddMyLibrary(this IServiceCollection services)
{
Assembly executingAssembly = Assembly.GetExecutingAssembly(); // MyLibrary assembly
services.AddAutoMapper(executingAssembly);
// ... setup other services
return services;
}
}
and in the API project I can now do this
Assembly executingAssembly = Assembly.GetExecutingAssembly();
services.AddAutoMapper(executingAssembly);
services.AddMyLibrary();
The code seems to work fine but AddAutoMapper will be called twice. Once for the API assembly and once for the library assembly. Should I stick to the first approach because AutoMapper should only be added once or is it fine to separate it?
The accepted answer was correct at the time but it would appear that things have changed in the recent past.
The AutoMapper.Extensions.Microsoft.DependencyInjection package has been updated to allow the call to AddAutoMapper() multiple times.
See PR Use Microsoft.Extensions.Options to configure AutoMapper for details. You will need to update the package to version 8.0.0 or higher to use it.
The code seems to work fine but AddAutoMapper will be called twice. Once for the API assembly and once for the library assembly. Should I stick to the first approach because AutoMapper should only be added once or is it fine to separate it?
You should stick to the first approach, because AddAutoMappper does nothing when called for the second, third etc. time, thus profiles and other AM related types from the assemblies passed to these calls won't be registered.
It can be seen in the beginning of the implementation of the private method which is called by all public AddAutoMapper overloads:
private static IServiceCollection AddAutoMapperClasses(IServiceCollection services, Action<IServiceProvider, IMapperConfigurationExpression> configAction,
IEnumerable<Assembly> assembliesToScan, ServiceLifetime serviceLifetime = ServiceLifetime.Transient)
{
// Just return if we've already added AutoMapper to avoid double-registration
if (services.Any(sd => sd.ServiceType == typeof(IMapper)))
return services;
followed by the actual registration code, which at the end registers IMapper.
Currently there is an open issue Allow usage of Options Pattern to configure AutoMapper #132 with exactly the same concerns as yours.
You can use abp moudule system to make the library register for themselves.
The doc is here: https://docs.abp.io/en/abp/latest/Module-Development-Basics
But the framework is a little heavy.If you don't want to use it,
I think you can do it this way: every library register the automapper itself ,and call the other library's register function it depends on.
Each library can add a helper class to do the registration
public static class ApiRegisterHelper
{
public static Assembly GetAssembly()
{
return Assembly.GetExecutingAssembly();
}
public static IServiceCollection AddLibrary(IServiceCollection services)
{
Assembly executingAssembly = GetAssembly();
services.AddAutoMapper(executingAssembly);
DaoRegisterHelper.AddLibrary(services);
return services;
}
}
public static class DaoRegisterHelper
{
public static Assembly GetAssembly()
{
return Assembly.GetExecutingAssembly();
}
public static IServiceCollection AddLibrary(IServiceCollection services)
{
Assembly executingAssembly = GetAssembly();
services.AddAutoMapper(executingAssembly);
OtherRegisterHelper.AddLibrary();
return services;
}
}
I havn't tested it,but it might be work.Hope it helps.

Why is my EF Core DbContext not bound by DI?

I have an Azure Function App with a function that runs on a blob trigger. I've proven that this function can run through the Azure Portal and responds to this blob trigger without issues... or at least it did.
Now that I've added functionality which makes use of EF Core (2.2.4), it gives me the following error, both when debugging locally and when publishing to Azure:
Microsoft.Azure.WebJobs.Host: Error indexing method 'ParseThings'. Microsoft.Azure.WebJobs.Host: Cannot bind parameter 'context' to type AvastusContext. Make sure the parameter Type is supported by the binding. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.).
I have a Startup class as instructed by Azure Function App documentation here, and have followed their example to the letter, aside from the following line in place of their configured example services:
[assembly: FunctionsStartup(typeof(AvstFunctionApp.Startup))]
namespace AvstFunctionApp
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddDbContext<AvastusContext>(options => options.UseSqlServer(Environment.GetEnvironmentVariable("AvastusDb")));
}
}
}
And the beginning of my function:
public static class ParseThings
{
[FunctionName("ParseThings")]
public static void Run([BlobTrigger("summaries/{name}", Connection = "StorageConnectionString")]Stream myBlob, string name, ILogger log, AvastusContext context)
I can confirm that the AddDbContext line is getting hit in a debugger, so presumably there's some bug happening behind the scenes here, or I'm doing something incredibly silly.
Things I've tried that haven't worked include:
Adding .BuildServiceProvider(true) to the AddDbContext line
Using WebJobsStartup instead of the more recently advertised FunctionsStartup
Downgrading to .NET Core 2.2.0
Changing the Function class and Run method from static to instance
Fixing incorrect namespace of the injected AvastusContext
It's also worth noting that there are two other functions in this Function App project which don't seem to have any serious issues, and I've been able to get dependency injection working using a similar method with EF Core for another (ASP.NET Core MVC) project in this solution.
Thank you in advance for any help anyone can provide!
P.S. I find it incredibly weird that there hasn't been anything describing this situation with the later versions of .NET Core, Azure Function Apps, and EF Core on the interwebs, which leads me to believe that this might be a simple mistake. Hopefully not.
perhaps one solution can be you can try injecting IServiceProvider in your function instead of AvastusContext like I have injected in the repository class below:
private readonly IServiceProvider serviceProvider;
public SomeRepository(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
using var context = this.serviceProvider.GetService<XYZDBContext>();
This will provide a context object to you. Also, Not sure why you are trying to access context in the function directly for good practice have a context class defined, and maintain repository to do any CRUD operation in the code.
Startup.cs you can add extra configurations like :
builder.Services.AddDbContext<XYZDBContext>(
options =>
{
options.UseSqlServer(
conn,
sqlServerOptionsAction:
sqlOptions =>
{
sqlOptions.EnableRetryOnFailure(maxRetryCount: 3, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
});
}, ServiceLifetime.Transient);
this configuration works perfectly fine in my current solution. Try this out.
Function app can't resolve dbcontext in functions as it can only resolve BindingContext. You need to create custom bindings to use dbcontext directly in function app.
Other way to get dbcontext injected via DI is to pass it to constructor and using a class level variable in the function.
public class ParseThings
{
private AvastusContext _context;
public ParseThings(AvastusContext context){
_context = context;
}
[FunctionName("ParseThings")]
public void Run([BlobTrigger("summaries/{name}", Connection = "StorageConnectionString")]Stream myBlob, string name, ILogger log){
// use _context here
}
}
If it still doesn't resolve you might want to look it into whether the functionsStartup is configured properly

2 MEF plugins using Entity Framework with different providers

I have a WPF application for which my users can create their own plugins by using MEF. Each plugin implements an interface that allows the main application to perform CRUD operations on some data source, e.g. a database.
I have created 2 plugins:
LocalDatabase - provides data from an SQLite database
RemoteDatabase - provides data from a MySQL database
Both are using Entity Framework to do their job. Each of those plugins needs to have its own implementation of the DbConfiguration class.
Now, the problem is that the WPF application loads those 2 plugins, but fails to assign each of them their own implementation of the DbConfiguration class, because it seems that you can have only one DbConfiguration per AppDomain.
So I always have only one of those plugins working.
I was thinking about having just one implementation of the DbConfiguration class and give each plugin an option to add its required configs to that, but the problem is that it creates some coupling between the WPF application and Entity Framework. I'd like to keep the Entity Framework stuff only inside the plugins without the need of modifying the WPF application. It shouldn't care about what plugins use to access their data source.
Is there any way of making it work this way? Could I maybe somehow create a separate AppDomain per each plugin, so maybe then each could use its own DbConfiguration class?
I've found a solution which is a bit hacky, but it does seem to work, so I thought I'd post it, in an unlikely case that someone would face the same issue somewhere in the future.
After some additional research, I've learnt that you can use the DbConfiguration.Loaded event to register some additional Dependency Resolvers for EF. So, in each plugin's constructor, I subscribe the event and add a new Dependency Resolver: SQLite for the LocalDatabase and MySql for the RemoteDatabase. I got rid of the custom DbConfiguration classes from each plugin.
This looked promising, but actually a new problem appeared - there were cases where LocalDatabase plugin called the MySql resolver and it actually returned the MySql implementation of the requested service type. Obviously the LocalDatabase plugin couldn't work with that, because it expected the SQLite implementation. And vice-versa.
So, each of the Resolvers, would actually need to check who called the GetService method - if it's some method from the same assembly that the custom resolver is in, it tries to resolve. Otherwise it's assumed that a resolver from different plugin should take care of that request and it returns null to actually let it do that.
The problem is that the GetService method doesn't supply any information about the requester. So that's where I came up with the hacky solution, which uses StackTrace to check whether any of the called methods belongs to the same Assembly that the current Resolver resides in.
public class CustomMySqlDbDependencyResolver : IDbDependencyResolver
{
private readonly Assembly _executingAssembly = Assembly.GetExecutingAssembly();
private readonly MySqlDependencyResolver _mySqlResolver = new MySqlDependencyResolver();
public object GetService(Type type, object key)
{
var stackTrace = new StackTrace();
StackFrame[] stackFrames = stackTrace.GetFrames().Skip(1).ToArray();
bool shouldResolve = stackFrames.Any(f => f.GetMethod().DeclaringType.Assembly.Equals(_executingAssembly));
if (!shouldResolve)
{
return null;
}
var resolvedService = _mySqlResolver.GetService(type, key);
return resolvedService;
}
public IEnumerable<object> GetServices(Type type, object key)
{
var service = GetService(type, key);
if (service != null)
{
yield return service;
}
}
}

Unable to register service

I'm trying to register a service using Prism autofac. However, I cannot seem to figure out a way to make this work. Everything I find on the internet is for older versions of prism and does not really show me how to use it now.
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<NavigationPage>();
containerRegistry.RegisterForNavigation<CashRegister>();
containerRegistry.RegisterForNavigation<HamburgerMenu>("Index");
containerRegistry.RegisterForNavigation<Inventory>();
containerRegistry.RegisterForNavigation<Navigation>();
containerRegistry.RegisterForNavigation<Start>();
containerRegistry.RegisterForNavigation<InventoryItemDetail>();
containerRegistry.RegisterForNavigation<FolderCreate>();
//containerRegistry.Register<SQLiteService>().As<ISQLiteService>();
var builder = new ContainerBuilder();
builder.RegisterType<SQLiteService>().As<ISQLiteService>();
builder.Build();
}
As you can see I tried it with the register container itself, but that did not really work since it did not recognize the .As method. Trying it with a new builder also gave me errors.
public class StartViewModel : BindableBase
{
public StartViewModel(ISQLiteService sqliteService)
{
}
}
Here I try to use the registered type.
can someone tell me what i'm doing wrong?
I found that you can use the build in builder using the GetBuilder() method but still getting an error.
The stack trace tells us, that there is a NullReferenceException thrown in the constructor of SQLiteService. Without seeing your code I'd guess that there is some mandatory constructor parameter, but Autofac is passing null.
See the Autofac documentation about how to pass parameters to your registered dependencies. Say we'll have to pass the name of the database file, we'd register SQLiteService as follows
containerRegistry.RegisterType<SQLiteService>()
.As<ISQLiteService>()
.WithParameter("databaseFile", "database.sqlite");

C# Unity why is module loading too late?

I have a module "Toolbar", "Toolbar" contains a UserControl and a ViewModel. The viewmodel is supposed to get a service called "IShapeService" injected into its constructor, however there's an issue.
I get the following error message when running my application:
The current type, Core.Services.IShapeService, is an interface and cannot be constructed.
Are you missing a type mapping?
The interface is mapped to the type in the ServicesModule which you can see below.
public class ServicesModule : IModule
{
private readonly IUnityContainer container;
public ServicesModule(IUnityContainer container)
{
this.container = container;
}
public void Initialize()
{
container.RegisterType<IShapeService, ShapeService>(new ContainerControlledLifetimeManager());
}
}
As far as I can tell by debugging, the issue is that the ServicesModule is not loaded early enough. I quickly tried using a PriorityAttribute (you can find it via google) on the module, but had no luck this time.
The weird thing is that it is working in another project with the same setup (as far I can see it is the same setup). The other project actually also uses the PriorityAttribute, but it is to determine tab order.
This is an image of the solution structure:
All projects reference the Core, but that is also it.
Can you spot what I'm doing wrong?

Categories

Resources