How can we use Automapper 10 in Extension Method? - .net-core

We have used Old version of Automapper in Static Class and Extension method
public static Account GetAccountDomain(this AccountViewModel viewModel)
{
return AutoMapper.Mapper.Map<AccountViewModel, Account>(viewModel);
}
and we had used this without caring about the technology of mapping in Domain and command Handler and Query Handler as following
accountViewModel.GetAccountDomain();
what can we do in dot net core and automapper 10 ?

Automapper has removed Static state for better performance. It should use with DI Pattern(IMapper) in all of framework that you need.

Related

Registering log4net named logger .NET Core service provider

I am struggling with finding a way to register log4net ILog within IServiceCollection services (.NET Core 2.1).
log4net LogManager provides a method that takes a Type as parameter so that it can be used when logging events. Here is an example call:
var log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
However when registering it with services at Startup method, I can use factory resolver, but still the type will be always the same. See the following excerpt:
private void SetServices(IServiceCollection services)
{
services.AddTransient(svc => CreateLog(MethodBase.GetCurrentMethod().DeclaringType)).;
}
protected ILog CreateLog(Type type)
{
return LogManager.GetLogger(type);
}
I was expecting that svc (IServiceProvider) will expose some ways to get to the type being actually resolved but there doesn't seem to be anything.
Also using reflection won't help (IMO, but I could be wrong) because ILog is activated prior to calling the resolved type ctor.
But maybe there is any extension on either MS side or log4net that would help resolving a named logger as explained on the beginning?
This is all to avoid having static members of ILog in any class that uses logging facility and use dependency injection instead.
Thanks, Radek
The way to do it is to implement and then register your own strongly typed Logger class that derives from ILogger.
.Net Core allows from to register generic type interface implementation with no type specified. In this case it would be:
services.Add(ServiceDescriptor.Singleton(typeof(ILogger<>), typeof(MyLogging.Logger<>)));
This allows all classes that require logging to use constructor injection as follows:
class A
{
public A(Ilogger<A> logger) {...}
}
Implementation of ILogger which a wrapper to log4net should be rather simple. Please let me know if you need an example.
Radek

Custom Authorize attribute without Identity and OWIN

I would like to construct a custom authorization attribute that does not invoke Identity or OWIN. Essentially, the only thing that it should have access to is a request context and the ability to either tell the MVC framework to process to continue to process the request or deny it.
Question Is there a simple way of achieving this in ASP.NET Core 2?
Some ideas
My understanding of ASP.NET Core is that it provides a way to customize the request pipeline using different middleware. I have seen that there are specific ones that are used for authentication, but they all seem to be very specific to Identity.
Is it better to to use a different type of filter?
A little bit late answer, but still.. the "old" way of overriding attributes comes back with the .Net Core 2.0, where in addition to the base class, you have to implement the IAuthorizationFilter interface:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class CustomAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter
{
private readonly string _someFilterParameter;
public CustomAuthorizeAttribute(string someFilterParameter)
{
_someFilterParameter = someFilterParameter;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
// you can play with the context here
}
}
More discussion here

.NET Core Web API: multiple [FromBody]?

I am converting code that was written in ASP.NET MVC to ASP.NET Core MVC. While I was converting the code, I encountered a problem. We used a method that has multiple parameters like this:
[HttpPost]
public class Search(List<int> ids, SearchEntity searchEntity)
{
//ASP.NET MVC
}
But when coding this in .NET Core, the ids parameter is null.
[HttpPost]
public class Search([FromBody]List<int> ids,[FromBody]SearchEntity searchEntity)
{
//ASP.NET Core MVC
}
When I place the ids parameter in the SearchEntity class, there is no problem. But I have lots of methods that are written like this. What can I do about this problem?
Can only have one FromBody as the body can only be read once
Reference Model Binding in ASP.NET Core
There can be at most one parameter per action decorated with [FromBody]. The ASP.NET Core MVC run-time delegates the responsibility of reading the request stream to the formatter. Once the request stream is read for a parameter, it's generally not possible to read the request stream again for binding other [FromBody] parameters.
MVC Core is stricter on how to bind model to actions. You also have to explicitly indicate where you want to bind the data from when you want to customize binding behavior.
I have used a solution where multiple parameters are sent as [FromBody] using a tuple:
[HttpPost]
public class Search([FromBody](List<int> ids, SearchEntity searchEntity) parameters)
{
//ASP.NET Core MVC
}

WCFService's DBContext to MVC App?

I have created a 'WCFService' application under 'WCFSolution' solution and generated the DBContext using Entity Framework from a Database 'DemoDB' in 'WCFService' application. and also created some CRUD methods in WCFService (Which is working great).
Then I created an empty 'WCFMVCApp' MVC application under the same solution ('WCFSolution') and also added the service reference to this app. Now i needed to create a controller ('HomeController') with the DBContext that is generated in that WCFService, so that i can generate the views based on the WCF models while creating the controller.
I could create a new EF in WCFMVCApp but it would defeat the purpose of WCF. Any way to do this. or is it possible? Any help would be appreciated. Thank you.
If you are using a WCF Service, in your MVCProject you don't have a DbContext to deal with and you should not add a reference to your WCF Service. You have some options.
Solution 1: Use a client
In your MVC Project create a data service client. Your service should be running and you need the data service tools installed. Then you can add a service reference and some proxy classes are generated for you.
WCF Data Services 5.6.0 RTM Tools Installer
Solution 2: Add a DbContext dll
You can have your DbContext living in a seperate class library that you reference in your service and your MVC project.
In both cases you are using DataServiceContext to perform CRUD operations. For the second one you may have to add an an implementation for ResolveType. To get an idea how to do this, this is how the automatic generated DataServiceContext would resolve types:
ODataSamples
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.OData.Client.Design.T4", "2.1.0")]
public Container(global::System.Uri serviceRoot) :
base(serviceRoot, global::Microsoft.OData.Client.ODataProtocolVersion.V4)
{
....
this.ResolveType = new global::System.Func<string, global::System.Type>(this.ResolveTypeFromName);
....
}
/// <summary>
/// Since the namespace configured for this service reference
/// in Visual Studio is different from the one indicated in the
/// server schema, use type-mappers to map between the two.
/// </summary>
protected string ResolveNameFromType(global::System.Type clientType)
{
global::Microsoft.OData.Client.OriginalNameAttribute originalNameAttribute = (global::Microsoft.OData.Client.OriginalNameAttribute)global::System.Linq.Enumerable.SingleOrDefault(global::Microsoft.OData.Client.Utility.GetCustomAttributes(clientType, typeof(global::Microsoft.OData.Client.OriginalNameAttribute), true));
if (clientType.Namespace.Equals("ODataSamples.CustomFormatService", global::System.StringComparison.Ordinal))
{
if (originalNameAttribute != null)
{
return string.Concat("ODataSamples.CustomFormatService.", originalNameAttribute.OriginalName);
}
return string.Concat("ODataSamples.CustomFormatService.", clientType.Name);
}
return null;
}

Configuring dependency injection with ASP.NET Web API 2.1

I'm creating an ASP.NET Web API 2.1 site and as I want to inject dependencies directly into the controllers, I've created my own implementation of IDependencyResolver so that StructureMap will handle that for me.
public class StructureMapDependencyResolver : IDependencyResolver
{
public IDependencyScope BeginScope()
{
return this;
}
public object GetService(Type serviceType)
{
return ObjectFactory.GetInstance(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return ObjectFactory.GetAllInstances(serviceType).Cast<object>();
}
public void Dispose()
{
}
}
I've then told Web API to use this class by adding this line to the Application_Start method in Global.asax
GlobalConfiguration.Configuration.DependencyResolver = new StructureMapDependencyResolver();
That compiled but when I tried to access any of the API methods in a browser I got an error like this
No Default Instance defined for PluginFamily System.Web.Http.Hosting.IHostBufferPolicySelector, System.Web.Http
That one was relatively easy to solve as I added a line to my StructureMap configuration
this.For<IHostBufferPolicySelector>().Use<WebHostBufferPolicySelector>();
However then I got other similar errors for other System.Web.Http classes and while I could resolve some of them I am stuck on how to deal with 3 of them, namely ITraceManager, IExceptionHandler and IContentNegotiator.
The issue is that TraceManager which seems to be the default implementation of ITraceManager is an internal class and so I can't reference it in my StructureMap configuration.
So am I going about this completely the wrong way or is there some other way to inject these internal classes?
I'd like to give you a suggestion and explanation why not to go this way, and how to do it differently (I'd even say better and properly).
The full and complete explanation of the inappropriate IDependencyResolver design could be found here: Dependency Injection and Lifetime Management with ASP.NET Web API by Mark Seemann
Let me cite these essential parts:
The problem with IDependencyResolver
The main problem with IDependencyResolver is that it's essentially a Service Locator. There are many problems with the Service Locator anti-pattern, but most of them I've already described elsewhere on this blog (and in my book). One disadvantage of Service Locator that I haven't yet written so much about is that within each call to GetService there's no context at all. This is a general problem with the Service Locator anti-pattern, not just with IDependencyResolver.
And also:
...dependency graph need to know something about the context. What was the request URL? What was the base address (host name etc.) requested? How can you share dependency instances within a single request? To answer such questions, you must know about the context, and IDependencyResolver doesn't provide this information.
In short, IDependencyResolver isn't the right hook to compose dependency graphs. **Fortunately, the ASP.NET Web API has a better extensibility point for this purpose. **
ServiceActivator
So, the answer in this scenario would be the ServiceActivator. Please take a look at this answer:
WebAPI + APIController with structureMap
An example of the ServiceActivator:
public class ServiceActivator : IHttpControllerActivator
{
public ServiceActivator(HttpConfiguration configuration) {}
public IHttpController Create(HttpRequestMessage request
, HttpControllerDescriptor controllerDescriptor, Type controllerType)
{
var controller = ObjectFactory.GetInstance(controllerType) as IHttpController;
return controller;
}
}
All we can do with StructureMap, is in place. The key features of the Web API framework are still in place... we do not have to hack them. And we are also rather using DI/IoC then Service locator
Just try using UnityHierarchicalDependencyResolver instead of the other one. It worked for me. This is for future reference if somebody would like to use Unity

Resources