I have got a strange Problem with strings in an asp.net 5 application, using asp.mvc 6 and the build in dependency injection (this is my conclusion). In a controller, I return a custom class created from a class library injected into the controller. To demonstrate the problem, I created a Test Class.
public class TestContainer
{
public string Caption { get; set; }
}
Then, in a controller, I return a list of these containers; one is created in the controller, and one is created in a class library which is injected in the controller.
In the controller:
[Route("api/testmethod")]
public List<TestContainer> TestMethod()
{
var testlocal = new TestContainer()
{
Caption = "aouäöü some name"
};
var testdpi = _businessLogic.ReturnTestContainer();
return new List<TestContainer>() {testlocal, testdpi};
}
In the injected library I use the following method to create the Testcontainer:
public TestContainer ReturnTestContainer()
{
var test = new TestContainer()
{
Caption = "aouäöü some name",
};
return test;
}
Now the strange thing happens. If I debug the application, it looks as follows:
Images can be found here and here.
For the local generate class, it shows:
aouäöü some name
For the Caption property, but for the class generated by the injected class it shows:
aou��� some name
For the caption property and the output in the browser, it looks as follows:
[{"Caption":"aouäöü some name"},{"Caption":"aou��� some name"}]
I can´t explain this behavior to myself. Any ideas?
Related
I have a method that uses Application variables to get information from an external file. Since Application variables are not used in unit tests, is there a way I can get the Application variables values from my Global.asax file and be able to use them in the test?
This is my test method:
[TestMethod]
public void TestGetCompanyList()
{
var accController = new AccSerController();
CInt cInt = new CInt();
cIn.Iss = "Other";
cIn.Tick = "BK";
var result
= accController.Clist(cIn) as IEnumerable<CList>;
Assert.IsNotNull(result);
}
Use the repository pattern. Your controller shouldn't have any idea about WebConfiguration.
//This defines the stuff that your controller needs (that your repository should contain)
public interface ISiteConfiguration
{
string Setting1 {get; set;}
}
//Use this in your site. Pull configuration from external file
public class WebConfiguration : ISiteConfiguration
{
public string Setting1 {get; set;}
public WebConfiguration()
{
//Read info from external file here and store in Setting1
Setting1 = File.ReadAllText(HttpContext.Current.Server.MapPath("~/config.txt"));
}
}
//Use this in your unit tests. Manually specify Setting1 as part of "Arrange" step in unit test. You can then use this to test the controller.
public class TestConfiguration : ISiteConfiguration
{
public string Setting1 {get; set;}
}
I'm using Ninject to perform dependency injection, but there's lots of other libraries out there. I'm going to omit some basic Ninject setup from my answer, because there's plenty of resources out there. But the below code shows how you'd specify in your web application to use WebConfiguration to fulfill the needs of an ISiteConfiguration.
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ISiteConfiguration>().To<WebConfiguration>();
}
Here's where the magic happens. When an instance of your controller is created in your web application, Ninject will look at the constructor and see that it's asking for ISiteConfiguration. And in your Ninject configuration, you told it to use WebConfiguration when it needs ISiteConfiguration. So Ninject will create a new instance of WebConfiguration and provide (inject) it to your controller.
public class AccountServiceController
{
ISiteConfiguration Config {get; set;}
//This is called constructor injection
public AccountServiceController(ISiteConfiguration config)
{
Config = config;
}
public ActionResult Index()
{
//Now you can use Config without needing to know about ISiteConfiguration's implementation details
//Get settings from Config instead of Application
}
}
You can also use Ninject in unit testing, but here's a simpler demo where we're not using it:
[TestMethod]
public void TestGetCompanyList()
{
//Arrange
var config = new TestConfiguration(){ Setting1 = "mysetting" };
var accountController = new AccountServiceController(config);
}
The result of all this is that you can use your controller's action methods easily for unit testing, because you can use whatever implementation of ISiteConfiguration you want.
I've done the following on some of my tests. Not ideal but it gets the job done.
if (System.Web.HttpContext.Current != null)
{
// Fill your application variable
}
else
{
// Get your data from somewhere else
}
There are two ways of unit testing such scenarios as far as I know.
First one is based on splitting controller function into two: one is controller function itself, another one implements the logic (e.g.: this is the one you test). Example:
Before:
public void MyControllerFunction()
{
var x = Context["variable"];
do-something-with-x;
}
After:
public void MyControllerFunction()
{
var x = Context["variable"];
MyControllerLogic(x);
}
internal void MyControllerLogic(object x)
{
do-something-with-x;
}
And then you test MyControllerLogic() function instead of MyControllerFunction() in unit test
Another methodology is create a surrogate context before invoking unit test.
Example:
var controller = new MyController();
controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();
controller.Request.Content = new StringContent("{ x: 21 }",
Encoding.Unicode);
controller.Request.Content.Headers.ContentType.MediaType =
"application/json";
Please note, I did not create HttpContext in 2nd example, I'm not sure if it's a requirement to have. You probably should be able to create it in similar way as well as the other variables you use. It's sort of a hack anyway, so treat it as such
Update:
This is an mvc plugin project, using MEF to get the controllers and actions at run time. http://www.fidelitydesign.net/?p=104
I added a new project and in its class I added an export of a type that is already being composed.
[Export(typeof(IController)), ExportMetadata("Name", "Clocks")]
public class ClocksController : Controller
{
public XmlActionResult Index()
{
var p = DeviceLogic.GetUnassigned;
}
[Import(typeof(DeviceLogic))]
DeviceLogic DeviceLogic { get; set; }
}
This gets composed in another project:
[Export]
public class ImportControllerFactory : DefaultControllerFactory
{
[ImportMany]
private IEnumerable<PartFactory<IController, IControllerMetadata>> ControllerFactories;
}
Application Start
[ImportMany]
private IEnumerable<ImportControllerFactory> ControllerFactories;
Controller factories is null, until I actually compose the parts
container.ComposeParts(this);
thats working fine, so I decided to try and emulate this to get devicelogic to appear in the project im having trouble with.
I created an emptry interface (IEmpty) for testing and tried this:
[Export(typeof(IEmpty))]
public class RequestProcessor : IEmpty
{
[Import(typeof(DeviceLogic))]
DeviceLogic DeviceLogic { get; set; }
}
and in my applciation start added
[ImportMany]
private IEnumerable<IEmpty> TestMef;
This is filled with the one instance after composition, so this seems to have worked. My question is does anyone have any suggestions as to why devicelogic is null in requestprocessor but not in clocksController.
You need to call MEF's SatisfyImportsOnce method after your instantiation :
YourMEFContainter.SatisfyImportsOnce(dataTransfer)
I'm trying to implement the the Microsoft Extensibility Framework (MEF) into a sample MVC-based web app. I'm using the SimpleCalculator example solution on the MEF Overview page. My goal is an application that can dynamically load a DLL extension from another project in order to extend the capabilities of the Model, essentially I want the MVC-Application to be a framework for other extensions to plug-into. First my setup:
Project 1 (MVC-Application, MEF Component Host):
I decorate the elements in my Model as follows:
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
namespace ExpressionParserPOC.Models
{
public class ExpressionModel
{
private CompositionContainer _container;
[ImportMany]
IEnumerable<Lazy<IExtensions,IExtensionName>> extensions { get; set; }
public ExpressionModel()
{
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog("C:\\local_visual_studio\\ExpressionParserPOC\\ExpressionParserPOC\\Extensions"));
//Create the CompositionContainer with the parts in the catalog
_container = new CompositionContainer(catalog);
_container.ComposeParts(_container);
//TEST: Can we access the extensions?
if (extensions != null)//<--NULL WHEN CONSTRUCTOR IS CALLED WHY? Expected GetMatrix() Function from DLL to be exposed
{
foreach (Lazy<IExtensions, IExtensionName> i in extensions)
{
Lazy<IExtensions, IExtensionName> foo = i;
}
}
}
}
public interface IExtensions
{
double[][] GetMatrix(string matrix);
}
public interface IExtensionName
{
Char Symbol { get; }
}
}
To test right now, I'm just calling the constructor for the Model from the Controller:
namespace ExpressionParserPOC.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Enter an Expression for Octave to evaluate";
//Instantiate an ExpressionModel composed of extensible parts
var model = new ExpressionModel();
return View(model);
}
}
}
Project 2 (DLL Project, MEF Component):
//PROJECT BUILD OUTPUTS TO THE EXTENSIONS DIRECTORY IN PROJECT 1 ABOVE
using System.ComponentModel.Composition;
namespace MyExtensions
{
//Project 1 already added as a reference
[Export(typeof(ExpressionParserPOC.Models.IExtensions))]
[ExportMetadata("Symbol", 'o')]
public class Octave : MyExtensions.IExtensions
{
//Other class properties, constructors, functions, etc.
#region FUNCTIONS
public double[][] GetMatrix(string matrix)
{
double[][] mat = new double[][];
//Do Stuff
return mat;
}
#endregion
}
public interface IExtensions : ExpressionParserPOC.Models.IExtensions
{
}
}
Problem is that the the extensions List in the host MVC application project never gets filled when I call the Model constructor from the Controller in that same project. I'm new to MEF development and am not sure what I'm doing wrong, is there something extra I need to consider since I'm working with an MVC application? Why won't the Project 1 extensions list get filled? Are my interface definitions wrong? The sample calculator application is a simple command line project and that seems to work fine, the only difference I see is that the external DLL project is in the same solution space, whereas with my example the solution spaces are independent.
A trivial mistake you have there in the ExpressionModel constructor. You are composing the container itself :)
_container.ComposeParts(_container);
The problem should be apparent instantly, because if the composition of the ExpressionModel actually ever happened, even if no extensions were discovered, the extensions property would be initialized with 0 items, but it wouldn't be null.
You need to compose the current model instance like this:
_container.ComposeParts(this);
Everything else seems to be alright and should be working fine after this correction.
Right now we have a dll file that contains all the database calls and i can't change it. However i need to call i from my Mvc 3 project. The process to call it is simple, i use the following:
ManageProvider.GetProxy<T>(ident);
T is an interface that i want to get the class back from (its like an IoC of its own) and ident is the user identification class. So by calling
var classReturned = ManageProvider.GetProxy<ICommunity>(new UserIden{ Email = "test#test.com" });
I would get a class back with all the community functions.
Now i want to implement Unity in my Mvc 3 project. The question is, can i somehow add these calls to the dll file through unity?
I want to resolve the call by using:
var classReturned = myContainer.Resolve<ICommunity>(new UserIden{ Email = "test#test.com" });
How can i register this in Unity (or is it even possible) ?
Update:
1) Is it better to call the methods with the email/user ident instead of defining a Dependency property? (ex below)
2) There is a bout 20 or so interfaces in the dll file right now. Should i add them all to the same reposatory? (ex below)
public class ProxyWrapper : IDllRepository
{
[Dependency]
public UserIdent UserIdent { get; set; }
public ICommunity GetCommunity()
{
return ManageProvider.GetProxy<ICommunity>(UserIdent);
}
public IDesktop GetDesktop()
{
return ManageProvider.GetProxy<IDesktop>(UserIdent);
}
}
public interface IDllRepository
{
ICommunity GetCommunity();
IDesktop GetDesktop();
}
Whats the best way and how would i call it from my code?
Does the [Dependency] attribute also fall into the Service Locator anti pattern?
Update 23.05.11
1) Yes, something like that. They contain all the logic that is provided to all the projects that includes the dll file.
Regarding the ManagerProvider. It accepts an interface and returns the class that is mapped to this interface. So for the community, the interface looks like this (removed a lot of calls to keep it short, there is also posts, comments, community create/update etc):
List<CommunityThread> GetThreads(int pStartRowIndex, int pMaximumRows, string pOrderBy, string pSearchExpression);
Guid? CreateThread(string pTitle, string pDescription, string pPostContent);
bool DeleteThread(Guid pThreadId);
List<CommunityThread> GetCommunityUserThreads(Guid pCommunityUserId);
2) What i can't update is how the ManageProvider.GetProxy works. The GetProxy is a class in the dll file that is hardcoded. Here is the part for the community. The class does the same for all the other interfaces as well, if typeof(interface) ... return class.
private static IManageProxy GetProxyForInterface<T>(UserIdent pIdent)
{
....
if (typeof(T).Equals(typeof(ICommunity)))
return new PCommunity();
....
}
3) Once registered using this new wrapper class, i can call it through the following code (MvcUnityContainer is a static class that only has a property called Container):
var c = MvcUnityContainer.Container.Resolve<IBackendRepository>(new PropertyOverride("UserIdent",
new UserIdent()));
Global.asax
IUnityContainer container = InitContainer();
MvcUnityContainer.Container = container;
DependencyResolver.SetResolver(new UnityMvcResolver(container));
The question is, do i need the static class MvcUnityContainer? Is it possible to configure the DependecyResolver to do that for me? Something like (problem is that it doesn't accept the override parameter):
var c = DependencyResolver.Current.GetService<IBackendRepository>(new PropertyOverride("UserIdent", new UserIdent()));
I think you need to hide the creation behind another abstraction, for instance:
public interface ICommunityRepository
{
ICommunity GetByEmailAddress(string address);
}
public class ManageProviderCommunityRepository
: ICommunityRepository
{
public ICommunity GetByEmailAddress(string address)
{
var id = new UserIden { Email = address };
return ManageProvider.GetProxy<ICommunity>(id);
}
}
This will hide both the ManageProvider and the UserIden behind this abstraction, and allows you to replace it later on with something more useful and makes testing easier.
Registration now is very easy:
RegisterType<ICommunityRepository, ManageProviderCommunityRepository>();
Instead of calling myContainer.Resolve (as you do in your example), inject the dependencies in your classes. This prevents you from using the Service Locator anti-pattern.
Perhaps you could do something like this, using the InjectionFactory:
myContainer.RegisterType<ICommunity>(
new InjectionFactory(c => ManageProvider.GetProxy<ICommunity>(new UserIden {Email = "test#test.com"})));
var classReturned = myContainer.Resolve<ICommunity>();
... Though you wouldn't be able to pass the UserIden as a parameter to the Resolve call, so I'm not sure if this is what you want.
To register all the public classes of the assembly you could perhaps iterate over Assembly.GetTypes() and register them in the same way?
I'm trying to figure out MEF's Constructor Injection attribute. I have no idea how I tell it to load the constructor's parameters.
This is the property I'm trying to load
[ImportMany(typeof(BUsers))]
public IEnumerable<BUsers> LoadBUsers { get; set; }
Here is the code I'm using to import the assemblies.
try
{
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()));
catalog.Catalogs.Add(new DirectoryCatalog("DI"));
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
Here is the class I'm trying to load
[Serializable]
[Export(typeof(BUsers))]
public class EditProfile : BUsers
{
[ImportingConstructor]
public EditProfile(string Method, string Version)
{
Version = "2";
Action = "Edit";
TypeName = "EditProfile";
}
When you use the ImportingConstructor attribute, the parameters to the constructor become imports. By default, what you are importing (the contract name) is based on the type of the parameter or property that your are importing into. So in this case the contract type for both your imports is string, and there's no real difference between the first and second parameter.
It looks like you are trying to use imports to supply configuration values, which isn't necessarily what it was designed for. To get it to do what you want, you should override the contract name for each of the parameters, like this:
[ImportingConstructor]
public EditProfile([Import("Method")] string Method, [Import("Version")] string Version)
{ }
Then you need exports for Method and Version in your container. One way to do this is just to add them directly:
var container = new CompositionContainer(catalog);
container.ComposeExportedValue("Method", "MethodValue");
container.ComposeExportedValue("Version", "2.0");
container.ComposeParts(this);
(Note that ComposeExportedValue is actually an extension method defined on the static AttributedModelServices class.)
If you want to read these values from a configuration file of some sort, you could create your own export provider which reads the configuration and provides the values in it as exports to the container.
An alternative way to handle this would be to just import an interface that provides access to the configuration values by name, and get the values you need from the body of the constructor.
I like Daniel's solution; however, only one thing I see is the tight coupling of parameter names between the actor (who creates CompopositionContrainer()) and Export part with [ImportingConstructor] for customized CTOR. For example, "Method" has two be matched in both places. It makes hard to maintain the Export part if the actor and Export part are in difference projects.
If it is possible, I would add the second CTOR to the Export part class. For example:
[Export(typeof(BUsers))]
public class EditProfile : BUsers
{
[ImportingConstructor]
public EditProfile(EditProfileParameters ctorPars)
: this(ctorPars.Method, ctorPars.Version) {}
public EditProfile(string Method, string Version)
{
Version = "2";
Action = "Edit";
TypeName = "EditProfile";
}
The class of EditProfileParameters should be straightforward: two properties of Method and Version:
[Export]
public class EditProfileParameters{
public string Method { get; set; }
public string Version { get; set; }
}
The key point is to add Export attribute to the class. Then MEF should be able to map this class to the parameter of EditProfile's CTOR.
Here is example to add the Export part to container:
var container = new CompositionContainer(catalog);
var instance1 = new EditProfileParameters();
// set property values from config or other resources
container.ComposeExportedValue(instance1);
container.ComposeParts(this);
Although late to the game, here's another approach that leverages a lesser-known feature of MEF: Property Exports
public class ObjectMother
{
[Export]
public static EditProfile DefaultEditProfile
{
get
{
var method = ConfigurationManager.AppSettings["method"];
var version = ConfigurationManager.AppSettings["version"];
return new EditProfile(method,version);
}
}
}
No usages are required for ObjectMother for this to work, and no attributes are required on EditProfile.