ServiceStack AutoQuery Is Null for Asp.Net.Core and NullReferenceException thrown at CreateQuery - asp.net-core

I've done the Plugins.Add(new AutoQueryFeature { MaxLimit = 100 }); and used it in startup Configure Method.
This is dto inherites QueryDb
I keep encountering AutoQuery is null and NullReferenceException thrown at AutoQuery.CreateQuery() Method. And CallStacks can not show ExternalCodes. I have no ideas where it gone wrong by referring to TechStacks Project.
The project references ServiceStack.Core 5.7.0
I'm able to get AutoQuery by using the below code.
var autoquery = TryResolve<IAutoQueryDb>()

None of your code samples show the 3 important things required for AutoQuery, the AutoQueryFeature plugin registration in your AppHost’s Configure(), the definition of your Service class that implements the Service base class, the public IAutoQueryDb AutoQuery { get; set; } public property.
If they’re configured correctly the IAutoQueryDb dependency should be injected.

Related

AutoMapper implementation in ASP.NET Core MVC

I am trying to implement AutoMapper in an ASP.NET Core MVC application using the techniques described in https://lostechies.com/jimmybogard/2016/07/20/integrating-automapper-with-asp-net-core-di.
Here is my startup.cs
public IServiceProvider ConfigureServices(IServiceCollection services)
{
…
services.AddMvc();
services.AddAutoMapper();
…
// Autofac configuration
return ConfigureAutofacContainer(services);
}
Here is my AutoMapper.Profile implementation
public class AutoMapperProfile_NetCore_DtoFromDao : Profile
{
#region ctor
public AutoMapperProfile_NetCore_DtoFromDao()
{
CreateMaps();
}
#endregion
#region Methods
protected void CreateMaps()
{
if (Mapper.Configuration.FindTypeMapFor(typeof(AddressType),
typeof(AddressTypeDto)) == null)
CreateMap<AddressType, AddressTypeDto>();
Mapper.Configuration.AssertConfigurationIsValid();
}
}
AutoMapperProfile_NetCore_DtoFromDao.CreateMaps() is being called by ServiceCollectionExtensions.AddAutoMapperClasses():
public static class ServiceCollectionExtensions
{
…
private static void AddAutoMapperClasses(IServiceCollection services,
Action<IMapperConfigurationExpression> additionalInitAction,
IEnumerable<Assembly> assembliesToScan)
{
…
Mapper.Initialize(cfg =>
{
additionalInitAction(cfg);
foreach (var profile in profiles)
{
cfg.AddProfile(profile);
}
});
…
}
}
I’m getting the following exception:
An exception of type 'System.InvalidOperationException' occurred in
AutoMapper.dll but was not handled in user code
Q - Is this due to the profile calling Mapper.Configuration.FindTypeMapFor() during Mapper.Initialization()?
Q - Is it possible to test for an existing mapping configuration before adding one during initialzation?
System.InvalidOperationException was unhandled by user code
HResult=-2146233079 Message=Mapper not initialized. Call Initialize
with appropriate configuration. If you are trying to use mapper
instances through a container or otherwise, make sure you do not have
any calls to the static Mapper.Map methods, and if you're using
ProjectTo or UseAsDataSource extension methods, make sure you pass in
the appropriate IConfigurationProvider instance. Source=AutoMapper
StackTrace:
at AutoMapper.Mapper.get_Configuration()
at Dna.NetCore.Core.BLL.Mappers.AutoMapperProfile_NetCore_DtoFromDao.CreateMaps()
in
C:\Src\AutoMapper.Extensions.Microsoft.DependencyInjection\src\Dna.NetCore.Core.BLL\Mappers\AutoMapperProfile_NetCore_DtoFromDao.cs:line
22
at Dna.NetCore.Core.BLL.Mappers.AutoMapperProfile_NetCore_DtoFromDao..ctor()
in
C:\Src\AutoMapper.Extensions.Microsoft.DependencyInjection\src\Dna.NetCore.Core.BLL\Mappers\AutoMapperProfile_NetCore_DtoFromDao.cs:line
13 InnerException:
OK. A few things here. Your AutoMapper config, the easiest way to build this is just:
services.AddAutoMapper(typeof(Startup));
That scans the assembly from the Startup class for Profiles, and automatically adds them using Mapper.Initialize. DO NOT call Mapper.Initialize after this.
Next, your profile. You're doing a lot of things you shouldn't. First, your profile is calling AssertConfigurationIsValid - don't. Next, it's checking for existing TypeMaps - don't. Just call the base CreateMap method, that's it.
Finally, you've got an extra AddAutoMapperClasses call. Don't use that. Get rid of it. You just need the "services.AddAutoMapper". The AddAutoMapper method calls Mapper.Initialize, with the Profile classes found in the assembly you've passed in.

Using the AspNetSynchronizationContext from WCF hosted in IIS

I'm hosting my .NET 4.5 WCF services in IIS.
There's a piece of information called "BusinessContext" (BC) that is stored in the OperationContext.Current instance, so that any logic downstream can reach it.
Everything worked fine until I introduced async/await, and I ran into this issue. #stephen-cleary mentioned ASP.NET uses the async-friendly AspNetSynchronizationContext to keep the HttpContext.Current across threads. Since I'm hosting in IIS I figured I should be able to take advantage of the AspNetSyncCtx in WCF, and use the HttpContext.Current instead of the OperationContext to store the BC.
I created a WCF service from scratch, which has targetFramework = 4.5, aspnet:UseTaskFriendlySynchronizationContext = true and aspNetCompatibilityEnabled = true set by default in the Web.config. I also added the AspNetCompatibilityRequirements = Required to my service.
At runtime I see the HttpContext.Current is there, but SynchronizationContext.Current is null. After an await the HttpContext becomes null, which is expected because there's no SyncCtx. Shouldn't it be set to AspNetSyncCtx when aspcompatibility is required? How does the AspNetSyncCtx get set in ASP.NET?
-- Possible solution.
Following #Stephen-cleary's here I went ahead and defined a custom SynchronizationContext to preserve the OperationContext across threads.
I'd like to hear the community's input regarding this implementation. Thanks.
public class OperationContextSynchronizationContext : SynchronizationContext
{
public override void Post(SendOrPostCallback d, object state)
{
OperationContext opCtx = OperationContext.Current;
InternalState internalState = new InternalState()
{
OpCtx = opCtx,
Callback = d,
State = state,
SyncCtx = this
};
ThreadPool.QueueUserWorkItem(new WaitCallback(InternalInvoker), internalState);
}
private void InternalInvoker(object internalState)
{
InternalState internalSt = internalState as InternalState;
SynchronizationContext.SetSynchronizationContext(internalSt.SyncCtx);
using (new OperationContextScope(internalSt.OpCtx))
{
internalSt.Callback.Invoke(internalSt.State);
}
}
private class InternalState
{
public SynchronizationContext SyncCtx { get; set; }
public OperationContext OpCtx { get; set; }
public SendOrPostCallback Callback { get; set; }
public object State { get; set; }
}
}
I ran into the issue (bug?) you mentioned where HttpContext.Current did not flow with async code in a WCF service hosted in IIS even with aspNetCompatiblity enabled and required.
I got my project working using the LogicalCallContext with CallContext.LogicalSetData and CallContext.LogicalGetData as described by Stephen Cleary in this blog post. I think setting/getting your business context thusly would work very well in your case and might be lighter weight and conceptually simpler than the custom SynchronizationContext. In your case you are having to Set your business context somewhere anyway ... might as well set it to the LogicalCallContext and I believe everything will be fine.
I'll explain my personal 'solution' in more detail, though I admit it is a bit hacky since I'm manually flowing the entire HttpContext object (and only in WCF methods). But again your case with your custom context object would seem to be a better fit.
In the ASP.NET web app I inherited, there were calls to HttpContext.Current littered throughout the business logic (not ideal). Obviously the project worked fine until I wanted several of the WCF methods in the app to be async.
A lot of the calls in the business logic would be from ASP.NET page loads, etc, where everything functions fine as it is.
I solved (kludged?) my problem in .NET 4.5 by creating a little helper class ContextHelper, and replaced all calls to HttpContext.Current with ContextHelper.CurrentHttpContext.
public class ContextHelper
{
public static void PrepareHttpContextFlow()
{
CallContext.LogicalSetData("CurrentHttpContext", HttpContext.Current);
}
public static HttpContext CurrentHttpContext
{
get
{
return HttpContext.Current ??
CallContext.LogicalGetData("CurrentHttpContext")
as HttpContext;
}
}
}
Now anytime the HttpContext.Current is defined, my helper method is essentially a no-op.
To make this work, the entry points for my WCF calls must call the PrepareHttpContextFlow method before the first call to await which is admittedly problematic and the main reason I consider this a kludge.
In my case this downside is mitigated by the fact that I have some OTHER manual calls required to add logical stack information for added error logging context that is lost when using async (since the physical stack information in an exception is not very useful for error logs in this case). So at least if I remember to do one of the "prepare for async" calls, I should remember to do the other :)

HttpContextBase.Request exception when using Ninject MVC3

I have a service that takes a dependency on HttpContextBase.
Ninject is injecting this for me already as it's set up in the MvcModule to return new HttpContextWrapper(HttpContext.Current) when HttpContextBase is requested
I want to use this service in Application_AuthenticateRequest, so i'm using property injection so that Ninject resolves it for me
When I try and access Request.UserHostAddress on the HttpContextBase I get a Value does not fall within the expected range exception
If I call HttpContext.Current.Request.UserHostAddress directly it works without problems
ExampleService.cs
public class ExampleService : IExampleService {
HttpContextBase _contextBase;
public ExampleService(HttpContextBase contextBase) {
_contextBase = contextBase;
}
public void DoSomething() {
var ip = HttpContext.Current.Request.UserHostAddress; <== this works
ip = _contextBase.Request.UserHostAddress; <== this fails
}
}
Global.asax
[Inject]
public IExampleService ExampleService { get; set; }
public void Application_AuthenticateRequest() {
ExampleService.DoSomething();
}
I'm missing something here, but I can't see what
Dependencies that are injected into classes live as long as the the class they get injected into, because the class holds a reference to them. This means that in general you should prevent injecting dependencies that are configured with a lifetime that is shorter than the containing class, since otherwise their lifetime is 'promoted' which can cause all sorts of (often hard to track) bugs.
In the case of an ASP.NET application, there is always just one HttpApplication instance that lives as long as the AppDomain lives. So what happens here is that the injected ExampleService gets promoted to one-per-appdomain (or singleton) and since the ExampleService sticks around, so does its dependency, the HttpContextBase.
The problem here of course is that an HTTP context -per definition- can't outlive a HTTP request. So you're storing a single HttpContextBase once, but it gets reused for all other requests. Fortunately ASP.NET throws an exception, otherwise you would probably be in much more trouble. Unfortunately the exception isn't very expressive. They could have done better in this case.
The solution is to not inject dependencies in your HttpApplication / MvcApplication. Ever! Although it's fine to do so when you're injecting singletons that only depend on singletons recursively, it is easy to do this wrong, and there's no verification mechanism in Ninject that signals you about this error.
Instead, always resolve IExampleService on each call to AuthenticateRequest. This ensures that you get an ExampleService with the right lifetime (hopefully configured as per-web-request or shorter) and prevents this kind of error. You can either call into the DependencyResolver class to fetch an IExampleService or call directly into the Ninject Kernel. Calling into the Kernel is fine, since the Application_AuthenticateRequest can be considered part of the Composition Root:
public void Application_AuthenticateRequest() {
var service = DependencyResolver.Current.GetService<IExampleService>();
service.DoSomething();
}

MyMessage<T> throws an exception when calling XmlSerializer

I am very new to nservicebus. I am using version 3.0.1, the last one up to date. And I wonder if my case is a normal limitation of NSB, I am not aware of.
I have an asp.net MVC application, I am trying to setup and in my global.asax, I have the following :
var configure = Configure.WithWeb()
.DefaultBuilder()
.ForMvc()
.XmlSerializer();
But I have an error with the XmlSerializer when dealing with one of my object:
[Serializable]
public class MyMessage<T> : IMessage
{
public T myobject { get; set; }
}
I pass trough :
XmlSerializer()
instance.Initialize(types);
this.InitType(type, moduleBuilder);
this.InitType(info2.PropertyType, moduleBuilder);
and then when dealing With T,
string typeName = GetTypeName(t);
typename is null and the following instruction :
if (!nameToType.ContainsKey(typeName))
ends in error. null value not allowed.
Is this some limitations to Nservicebus, or am I messing something up?
NServiceBus intentionally does not support generic message types to encourage you to make your message schema explicit.

Passing an Entity Framework Context object to WCF

I need to pass a Context object from EF into a WCF method.
Normally, I create the Context object in the WCF method and dispose of it right before the end of the method call which works just fine for most of my methods.
However, I need to pass the Context object (specifically the DBContext) over from the MVC controller to my specific WCF method because I have caching enabled for some lookup tables. I need this specific Context object passed over (the one I set in the Application_Start method of the Global.asax file) rather than what I do in the sentence above because I use this specific object for the SqlDependency. If I try and create the DBContext object brand new, I can't use the SqlDependency becuase I will get an error informing me that the SqlDependency needs to be enabled before the database call.
The problem is that I'm getting the following error (shortened for brevity) when I try and start my WCF Test Client tool which I know has something to do with not properly declaring a KnownType attribute (ie the DBContext object). Note that the WCF project compiles just fine. I need some help with this specific part since I have never used a KnownType in my WCF service. They have all been simple types (int, string, etc).
Error: Cannot obtain Metadata from http://localhost:8732/Design_Time_Addresses/YeagerTechWcfService/YeagerTechWcfService/mex
If this is a Windows (R) Communication Foundation service to which you
have access, please check that you have enabled metadata publishing at
the specified address. For help enabling metadata publishing, please
refer to the MSDN documentation at
http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange
Error URI:
http://localhost:8732/Design_Time_Addresses/YeagerTechWcfService/YeagerTechWcfService/mex
Metadata contains a reference that cannot be resolved:
I have the following OperationContract code in my WCF service:
[OperationContract]
IEnumerable<Category> GetCategories(YeagerTechEntities DbContext);
I have the following DataContract code in my WCF service:
namespace YeagerTechModel
{
[Serializable]
[DataContract(IsReference = true)]
[KnownType(typeof(YeagerTechEntities))]
public partial class Category
{
public Category()
{
this.Projects = new HashSet<Project>();
}
[DataMember]
public short CategoryID { get; set; }
[DataMember]
public string Description { get; set; }
[DataMember]
public virtual ICollection<Project> Projects { get; set; }
}
}
Finally, the following is my WCF method:
public IEnumerable<YeagerTechModel.Category> GetCategories(YeagerTechEntities DbContext)
{
//YeagerTechEntities DbContext = new YeagerTechEntities();
DbContext.Configuration.ProxyCreationEnabled = false;
IEnumerable<YeagerTechModel.Category> category = DbContext.Categories.Where(p => p.CategoryID > 0).AsCached("Categories").ToList();
//IEnumerable<YeagerTechModel.Category> category = DbContext.Categories.Where(p => p.CategoryID > 0);
CloseConnection(DbContext);
return category;
}
You need singleton object following registry / service locator pattern. This object will hold reference to your global objects. For example at application start you will fill this object with your context using SqlDependency and you will use the registry to access this context in your controller's actions and service's operations.
Anyway work with this very carefully. SqlDependency and EF doesn't play nice together because it will make your context long living. Long living context is in most cases anti-pattern. Never ever use that context for anything else then loading cached data. Don't use it for data modification or loading non cached relations! Load entities as non-tracked (AsNoTracking extension method on query) in the first query and turn off proxy creation and lazy loading for that context.
Also be aware that query in EF is always executed in the database. I'm not sure what your AsCached is supposed to do but I somehow doubt it will work. What you need is probably:
var category = DbContext.Categories.Local
.Where(p => p.CategoryID > 0)
.ToList();
I would not use SqlDependency with EF. I would use ADO.NET and SQL directly. For caching in EF I would check EF Caching provider to use second level cache which is in most cases enough.