Projects with StructureMap and Unobtrusive don't register Subscriptions - structuremap

Current Production NUGET build.
Windows 8 x64
VS2012
I followed the sample on how to create a pub/sub.
The default builder was swapped out for structuremap, and everything worked fine.
I delete the queues and the database for raven and the console complains about client#machine name doesn't exist.
I delete the queues and db again and comment out the structuremap stuff and restore the default builder and everything works again.
Same problem with new projects that don't use the default builder to setup the queues first.
Initial
Configure.With()
.DefaultBuilder()
.DefiningEventsAs(t => t.Namespace != null && t.Namespace.EndsWith("Events"));
With StructureMap
public void Init()
{
Configure.With()
//.DefaultBuilder()
.StructureMapBuilder(new Container(new DependencyRegistry()))
.JsonSerializer()
.DefiningEventsAs(t => t.Namespace != null && t.Namespace.EndsWith("Events"));
}
public class DependencyRegistry : Registry
{
public DependencyRegistry()
{
Scan(x =>
{
x.AssembliesFromApplicationBaseDirectory();
x.WithDefaultConventions();
});
}
}

DefiningEventsAs needs to go right after the call to With(). This is a known issue we'll make sure to fix it in a future version.

Related

Use ASP.NET MVC Unity for Data Caching

I have a ASP.Net MVC project running on .NET 4.6.1 Framework.
I have recently added Unity.Mvc 5 IoC framework for dependency injection
In order to have flexibility for unit testing and other, I moved my Unity Configuration to a separate class library so that I can call the Unity Register methods from Unit test projects and other as needed.
Here is my high-level solution design.
I would like to use the same class library to implement application cache.
When I installed Unity.Mvc5 from nuget package it added following references (I added some of them manually) :
Microsoft.Practices.EnterpriseLibrary.Caching 5.0.505.0
Enterprise Library Shared Library 5.0.505.0
Microsoft.Practices.ServiceLocation 1.3.0.0
Microsoft.Practices.Unity 4.0.0.0
Microsoft.Practices.Unity.Configuration 4.0.0.0
Microsoft.Practices.Unity.Interception 2.1.505.0
Microsoft.Practices.Unity.Interception.Configuration 2.1.505.0
Microsoft.Practices.Unity.RegistrationByConvention 4.0.0.0
I tried few articles to implement Application Block Cache Management so that I can cache data in my Service Implementer layers, but all those documentations are showing code examples which is expecting Unity 2.xxx version.
Here is my Unity Configuration
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<UserManager<User>>(new HierarchicalLifetimeManager());
container.RegisterType<IUserStore<User>, UserStore<User>>(new HierarchicalLifetimeManager());
container.RegisterType<DbContext, OfficeGxDbContext>(new HierarchicalLifetimeManager());
container.RegisterType<IAppSetting, AppSettingService>();
container.RegisterType<ISubscription, SubscriptionService>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
In my AppSettingService.cs I have get all method
public List<AppSetting> All()
{
using (var context = new MyDbContext())
{
//CachecKeyItem.AppSettingsAll
return context.AppSettings.Where(x => !x.IsDeleted)
.Include(x => x.Module).ToList();
}
}
I want to store this data in cache and reuse it. Similarly do this across all projects I have in my solution and if there is any update or add or delete for any DB records, I want the cached object to refresh it so that cached object is always in sync with DB data
I ended up doing something like this
public interface ICacheService
{
T GetOrSet<T>(string cacheKey, Func<T> getItemCallback) where T : class;
}
Service Implementor
public class InMemoryCache : ICacheService
{
public T GetOrSet<T>(string cacheKey, Func<T> getItemCallback) where T : class
{
if (MemoryCache.Default.Get(cacheKey) is T item) return item;
item = getItemCallback();
MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(8));
return item;
}
}
use like this
_cacheService.GetOrSet(CachecKeyItem.AppSettingsAll, () => context.AppSettings
.Where(x => !x.IsDeleted)
.Include(x => x.Module).ToList());
Now my question is, when there is any change to data, like add/edit/delete, how do I refresh the cache in most efficient way? I know deleting the key would be one, is there a better way?
It slightly depends on if your running in a single server system or multi server system. Its generally better to always design for multi-server that way if you ever decide to scale out your already sorted.
So assuming you can get a message to fire off when your cache invalidates to all the servers without issue then the easiest way is to delete your cache key... now that also brings a few areas of optimization that can be looked at.
Is this cached data utilized heavily, in which case may you benefit from a pre-fetch cache where you either send the updated cached entry to all servers or require all servers to ask for it? Is it used very little in which case you don't really want to re-populate until its requested otherwise your needlessly bloating your application.

Autofac Dependency Resolver ocasionally crash on controller resolving mvc 5 (DependencyResolutionException)

i have following problem, I have web application in mvc5 with autofac dependency injection and generic data repositories. Usually all is working fine, the web is runing with no error, but after some time online following error appear:
The dependency resolver is folowing:
public class IoCConfig {
public static IContainer BuildContainer < T > () {
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterApiControllers(typeof(T).Assembly);
builder.RegisterControllers(typeof(T).Assembly);
try {
foreach(var type in AssemblyLoader.Load < IDependency > ()) {
var registration = builder.RegisterType(type);
foreach(var interfaceType in type.GetInterfaces().Where(itf => typeof(IDependency).IsAssignableFrom(itf))) {
registration = registration.As(interfaceType);
if (typeof(IUnitOfWorkDependency).IsAssignableFrom(interfaceType)) {
registration = registration.InstancePerRequest();
}
}
}
} catch (Exception ex) {
throw ex;
}
return builder.Build();
}
}
and is executed on Application_Start.
The example constructor of the controller is:
[Authorize]
public class ClassesManagmentController: Controller {
IDepartmentsRepository _departmentRepo;
IClassesRepository _classesRepo;
IClassesCategoriesRepository _classesCategoriesRepo;
public ClassesManagmentController(IDepartmentsRepository departmentsRepo,
IClassesRepository classesRepo,
IClassesCategoriesRepository classesCatiegoriesRepo) {
_departmentRepo = departmentsRepo;
_classesRepo = classesRepo;
_classesCategoriesRepo = classesCatiegoriesRepo;
}
// the rest of the Controller code
}
And the example repo interface and class are:
public class ClassesCategoriesRepository: Bases.RepositoryBase < ClassesCategoryDto > , IClassesCategoriesRepository {
public ClassesCategoriesRepository(IContextFactory factory): base(factory) {
}
}
public interface IClassesCategoriesRepository: IGenericRepository < ClassesCategoryDto > , IDependency {}
The repositories are in dedicated project, the dependency resolver and identification interfaces (IDependency) are in dedicated project, and web is in one more project.
I checked already twice if all projects of my solution are referencing the same autofac and mvc libraries. i was trying different resolving types but i dont found solution yet.
Any help will be appreciated.
If things are working for a while and then stop working chances are IIS is recycling the app pool and your assembly scanning mechanism isn't picking up all the assemblies correctly. Per the documentation:
When hosting applications in IIS all assemblies are loaded into the AppDomain when the application first starts, but when the AppDomain is recycled by IIS the assemblies are then only loaded on demand.
To avoid this issue use the GetReferencedAssemblies() method on System.Web.Compilation.BuildManager to get a list of the referenced assemblies instead:
var assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>();
That will force the referenced assemblies to be loaded into the AppDomain immediately making them available for module scanning.
If this controller never works but everything else does, do a test in one of the working controllers - try to manually resolve the IDepartmentsRepository and see if you can. If you can, then... strange things are afoot. But if you can't, then it means that particular repo isn't being picked up by the scanning and isn't registered, so the exception is telling you exactly what's wrong.

How to update breeze.js library

I could use some guidance on how to manually update between versions of Breeze and it's dependencies. I do not believe I can just update with the NuGet Package Manager.
I have been developing my Single Page App with Breeze, Knockout, WebAPI and so forth. I have been using Breeze version 0.61 and want to upgrade to the latest version so I can take advantage of the ODataActionFilters and not have to parse the Request.QueryString to pull out parameters and filters. For example when I call
var getMachineById(machineId) {
var query = EntityQuery
.from("Machines")
.where("machineId", "eq", machineId);
return manager.executeQuery(query)
.then(function (data) {
do_something_with(data.results);
})
.fail(queryFailed);
}
There has to be a way for Breeze to handle that for me, so I can just do something like this:
[AcceptVerbs("GET")]
public IQueryable<Machine> Machines()
{
return _contextProvider.Context.Machines;
}
instead of
// eg "?$filter=machineId%20eq%205"
[AcceptVerbs("GET")]
public IQueryable<Machine> Machines()
{
IQueryable<Machine> x = _contextProvider.Context.Machines;
List<ODataQueryString> list = null;
string qs = Request.RequestUri.Query.ToString(CultureInfo.CurrentCulture);
list = new ODataQueryStringParser(qs).Parse();
if (list != null)
{
int machineId = int.Parse(list[0].Value); // covert string to an int
x = x.Where(o => o.MachineId == machineId);
}
return x;
}
I notice that the Attribute decoration in the Controller has changed in the Samples. Do I need to change mine too?
namespace PilotPlantBreeze.Controllers
{
[JsonFormatter, ODataActionFilter]
public class BreezeController : ApiController
{
readonly EFContextProvider<PilotPlantDbContext> _contextProvider =
new EFContextProvider<PilotPlantDbContext>();
[AcceptVerbs("GET")]
public string Metadata()
{
return _contextProvider.Metadata();
}
[AcceptVerbs("POST")]
public SaveResult SaveChanges(JObject saveBundle)
{
return _contextProvider.SaveChanges(saveBundle);
}
... etc.
}
}
I have my 3rd party libraries in a folder ~\Scripts\lib. If I use the NuGet package manager to update, it puts all the replacements in ~\Scripts. How do I move the files into the lib folder without messing up my Team Foundation Server (Azure) source control?
Are the runtime versions of Antlr3.Runtime.dll, Breeze.WebApi.dll, Irony.dll, Newtonsoft.Json.dll, WebActivator.dll and maybe WebGrease.dll compatible between versions. I bet not. Is there something I have to change in Visual Studio?
Can I just change version entries from the package folder in packages.config?
Thanks.
I think that your best approach would be to remove any existing breeze '.js' files and the webApi and irony.dlls from your project and then simply install the latest breeze nuget package. After installing the nuget package you can go ahead and move the files to other locations within the project to match their "old" locations. I'd do the same for the NewtonSoft nuget package as well, just in case ( breeze will add this back for you). Going forward, you can just update to latest nuget and then move the files.
As you noticed you will also need to replace these attributes
[JsonFormatter, ODataActionFilter]
with this attribute
[BreezeController]
This assumes that you are not running a beta version of ASP.MVC4. I think there are posts in other forums that discuss how to migrate away from the beta.

Unity Interception using auto wiring

I got Unity interception working using a HadlerAttribute and an instance of ICallHandler. To get it working all I have to do is decorate the class with the [Trace] attribute, and the interceptor works great.
[Trace]
public interface IPersonService
{
string GetPerson();
}
However I would like to have interception working for all my methods in a couple of assemblies. So I am using Unity AutoRegistration to set up my container as follows:
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
//container.AddNewExtension<UnityInterfaceInterceptionRegisterer>();
container.
ConfigureAutoRegistration().
ExcludeSystemAssemblies().
LoadAssemblyFrom(typeof(PersonService).Assembly.Location).
Include(If.ImplementsITypeName, Then.Register()).
ApplyAutoRegistration();
return container;
}
Works great, except when I attempt to setup global registration as per this post:
http://unity.codeplex.com/discussions/281022
I have a UnityContainerExtension configured as follows, where MVC4Unity is my DLL:
public class UnityInterfaceInterceptionRegisterer : UnityContainerExtension
{
protected override void Initialize()
{
base.Container.AddNewExtension<Interception>();
base.Container.Configure<Interception>().
AddPolicy("LoggingPolicy").
AddMatchingRule<AssemblyMatchingRule>
(new InjectionConstructor("MVC4Unity")).
AddCallHandler(new TraceCallHandler());
base.Context.Registering += new EventHandler<RegisterEventArgs>(this.OnRegister);
}
private void OnRegister(object sender, RegisterEventArgs e)
{
IUnityContainer container = sender as IUnityContainer;
if (e != null && e.TypeFrom != null && e.TypeFrom.IsInterface)
{
container.Configure<Interception>()
.SetInterceptorFor(e.TypeFrom, e.Name, new InterfaceInterceptor());
}
}
}
Unfortunately it is always throwing a StackOverflowException (!) when it goes into the OnRegister method.
The question then is, has anyone implemented assembly or even namespace wide interception using Unity, and was this the way to go?
[EDIT]
It seems that no matter what I add in the AddMatchingRule line below, that the OnRegister handler is invoked for all included assemblies as well! ( for example even the Microsoft.* namespace assemblies!)
base.Container.AddNewExtension<Interception>();
base.Container.Configure<Interception>().
AddPolicy("LoggingPolicy").
// see what other types of matchings rules there are!
AddMatchingRule<NamespaceMatchingRule>
(new InjectionConstructor("MVC4Unity.*")).
AddCallHandler(new TraceCallHandler());
base.Context.Registering += new EventHandler<RegisterEventArgs>(this.OnRegister);
I'm late with my answer, but maybe someone will find this useful.
If I understood the problem correctly you need to apply one matching rule to multiple assemblies. For these kind of tasks you can use AssemblyMatchingRule (MSDN).
container.Configure<Interception>()
.AddPolicy("logging")
.AddMatchingRule<AssemblyMatchingRule>(
new InjectionConstructor(
new InjectionParameter("YourAssemblyName")))
.AddCallHandler<LoggingCallHandler>(
new ContainerControlledLifetimeManager(),
new InjectionConstructor(), new InjectionProperty("Order", 1));
In your last code snippet i think you need to remove dot asterisk in the end of namespace in order to add MVC4Unity namespace to your NamespaceMatchingRule.
For additional information please check this link - Policy Injection MSDN

Avoiding missing views in ASP.NET MVC

When testing an ASP.NET MVC 2 application I hit a problem when a view could not be located.
Looking at the code I realised that the aspx file for the view had not been added to the source control repository. On this project that's quite easy to do as we use StarTeam for source control and it doesn't show new folders when checking in. This view was for a new controller and so a new folder was created for it and it was therefore missed.
Our build server (using Hudson/MSBuild) didn't pick up on this, as the code still builds fine with the aspx file missing. Our controller unit tests test the ActionResults which obviously still pass without the view there.
This got picked up in system testing but how can I catch this earlier (ideally on the build server).
Thanks in advance
You can write unit tests that test the actual view, and then if the unit test doesn't pass on the build server, you know you have a problem. To do this, you can use a framework such as this:
http://blog.stevensanderson.com/2009/06/11/integration-testing-your-aspnet-mvc-application/
With this you can write unit tests such as this (from the post)
[Test]
public void Root_Url_Renders_Index_View()
{
appHost.SimulateBrowsingSession(browsingSession => {
// Request the root URL
RequestResult result = browsingSession.ProcessRequest("/");
// You can make assertions about the ActionResult...
var viewResult = (ViewResult) result.ActionExecutedContext.Result;
Assert.AreEqual("Index", viewResult.ViewName);
Assert.AreEqual("Welcome to ASP.NET MVC!", viewResult.ViewData["Message"]);
// ... or you can make assertions about the rendered HTML
Assert.IsTrue(result.ResponseText.Contains("<!DOCTYPE html"));
});
}
What version of StarTeam are you running? In StarTeam 2008 (not sure when this feature was first added) within a selected project/view, you can select from the menu Folder Tree->Show Not-In-View Folders. This will show folders you have on local disk that have not been added to the project (they will appear with the folder icon colored white).
This is an old question, but if anyone still looking for this you ought to try SpecsFor.Mvc by Matt Honeycutt.
Not only it can be used to make sure the Views are properly included/added in the source control, it can even do integration test to make sure those Views are valid.
Link to its website: http://specsfor.com/SpecsForMvc/default.cshtml
Link to the nuget package: https://www.nuget.org/packages/SpecsFor.Mvc/
Link to github: https://github.com/MattHoneycutt/SpecsFor
Here is a code snippet taken from the website showing how to use it.
public class UserRegistrationSpecs
{
public class when_a_new_user_registers : SpecsFor<MvcWebApp>
{
protected override void Given()
{
SUT.NavigateTo<AccountController>(c => c.Register());
}
protected override void When()
{
SUT.FindFormFor<RegisterModel>()
.Field(m => m.Email).SetValueTo("test#user.com")
.Field(m => m.UserName).SetValueTo("Test User")
.Field(m => m.Password).SetValueTo("P#ssword!")
.Field(m => m.ConfirmPassword).SetValueTo("P#ssword!")
.Submit();
}
[Test]
public void then_it_redirects_to_the_home_page()
{
SUT.Route.ShouldMapTo<HomeController>(c => c.Index());
}
[Test]
public void then_it_sends_the_user_an_email()
{
SUT.Mailbox().MailMessages.Count().ShouldEqual(1);
}
[Test]
public void then_it_sends_to_the_right_address()
{
SUT.Mailbox().MailMessages[0].To[0].Address.ShouldEqual("test#user.com");
}
[Test]
public void then_it_comes_from_the_expected_address()
{
SUT.Mailbox().MailMessages[0].From.Address.ShouldEqual("registration#specsfor.com");
}
}
}

Resources