Dependency Injection Involving Struct types - c#

I have a class as shown below,
public class AccessToken : IAuthToken
{
/// <summary>
/// Initializes a new instance of the <see cref="AccessToken"/> class.
/// </summary>
/// <param name="token">The token.</param>
/// <param name="validTo">The valid to.</param>
public AccessToken(string token, DateTimeOffset validTo)
{
ValidTo = validTo;
Token = token;
}
///<inheritdoc />
public DateTimeOffset ValidTo { get; private set; }
/// <summary>
/// Gets the RAW Jwt token value.
/// This value is encoded and represents the Jwt token.
/// </summary>
/// <value>
/// The token.
/// </value>
public string Token { get; private set; }
}
The DI code goes like this,
return services
.AddTransient<IAuthToken, AccessToken>()
.AddTransient<IAuthTokenService, AuthTokenService>()
.AddSingleton<IIdentityDiscovery, IdentityDiscovery>()
.AddTransient<IIdentityTokenClient, IdentityTokenClient>()
.AddTransient<IDiscoveryClientRetryPolicy, DiscoveryClientRetryPolicy>()
.AddTransient<ITokenClientRetryPolicy, TokenClientRetryPolicy>()
.AddSingleton<IRetryPolicyOptions>(provider => retryOptions);
The whole thing is packaged as a nuget. When this DI code is called from .net461 it works fine but when used in net core 6, I get an error stating it's unable to resolve type string and DateTimeOffset. I tried to inject a dummy string and the string error vanished but the struct DateTimeOffset persisted. Does .net6 interpret this DI in a different way?

If your classes in your nuget package tries to resolve this IAuthToken instance then you can add the following registration to your main app to override the registration that comes from the nuget. The registration order is important, so be sure to execute service registration from your nuget first.
services.AddTransient<IAuthToken, AccessToken>(
serviceProvider =>
{
// You can resolve any service that can provide the token and validTo parameters.
var tokenInfoProvider = serviceProvider.GetRequiredService<...>();
// Get the parameter values.
// Either from the tokenInfoProvider or specify it directly here.
string token = String.Empty;
DateTimeOffset validTo = DateTimeOffset.UtcNow.AddHours(1);
// Create and return the access token instance.
return new AccessToken(token, validTo);
}
);
If only the app tries to resolve an IAuthToken then I would suggest to create a factory (e.g. IAccessTokenFactory) that you can use to create the AccessToken instance with specific ctor parameters dynamically. Then register its implementation and inject IAccessTokenFactory where you need to get a new IAuthToken instance. So that you can keep your nuget code as it is now.
public interface IAccessTokenFactory
{
IAuthToken Create(string token, DateTimeOffset validTo);
}
public class AccessTokenFactory : IAccessTokenFactory
{
public IAuthToken Create(string token, DateTimeOffset validTo)
{
return new AccessToken(token, validTo);
}
}
// register this instead of the AccessToken
services.AddSingleton<IAccessTokenFactory, AccessTokenFactory>();

Related

WebAPI: Make operation method enabled/visible only for minimum/maxium API version

I have a simple WebAPI controller, looks like this:
[Authorize]
[ApiController]
[Route("v{version:apiVersion}/[controller]")]
[Route("[controller]")]
[ApiVersion("1.0")]
[ApiVersion("2.0")]
[ApiVersion("3.0")]
[RequiredScope(RequiredScopesConfigurationKey = "AzureAd:Scopes")]
public class WeatherForecastController : ControllerBase
{
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger) {_logger = logger;}
/// <summary>
/// defined version neutral
/// </summary>
[ApiVersionNeutral]
[HttpGet("health")]
public string Health()
{
return "I'm Version independent";
}
/// <summary>
/// defined in version 1 - yet valid for all API versions
/// </summary>
[HttpGet("ring")]
public string Ring()
{
return "All API Versions";
}
/// <summary>
/// defined in version 1
/// </summary>
[MapToApiVersion("1.0")]
[HttpGet("ping")]
public string Ping()
{
return "API Version (1)";
}
/// <summary>
/// defined in version 2
/// </summary>
[MapToApiVersion("2.0")]
[MapToApiVersion("3.0")]
[HttpGet("ping")]
public string Ping2()
{
return "API Version (2) [a changed version from V1]";
}
/// <summary>
/// defined in vresion 3
/// </summary>
[MapToApiVersion("3.0")]
[HttpGet("pong")]
public string Pong()
{
return "API Version 3";
}
}
When I add a new version because either a new operation arrived or an operation has changed, I have now to add the MapToApiVersion attribute for every method, which already has at least one such attribute and should exist in further version as well and also for all methods which should not anymore exposed in the new version.
For example for a new version 4, I would like to archive the ring operation, means I have to change it as follow (compare with complete class code above):
[MapToApiVersion("1.0")]
[MapToApiVersion("2.0")]
[MapToApiVersion("3.0")]
[HttpGet("ring")]
public string Ring()
{
return "All API Versions";
}
And the ping operation, exposed through ping2 method, which should further exist in new version (compare with complete class code above) to be changed like this:
[MapToApiVersion("2.0")]
[MapToApiVersion("3.0")]
[MapToApiVersion("4.0")]
[HttpGet("ping")]
public string Ping2()
{
return "API Version (2) [a changed version from V1]";
}
So I'm wondering, if there is a simpler way to declare a controller method (not the operation, this could still exists through another method ...) to be active from a certain API version or up to a certain API version. Simply spoken I search something like MapToApiVersionMin("4.0") and MapToApiVersionMax("3.0").
And besides, I haven't found out, what the difference is between ApiVersion and MapToApiVersion attribute on method level. For me it seems to do the same job ...
I'm working against .NET 6
Thanks for your replies.

How to include multiple policies

I have defined 2 policies, ADD and SUB as shown below.
options.AddPolicy("ADD", policy =>
policy.RequireClaim("Addition", "add"));
options.AddPolicy("SUB", policy =>
policy.RequireClaim("Substraction", "subs"));
All what I want to do isto include 2 policies on a controller method. How can I perform this operation.
[Authorize(Policy = "ADD, SUB")]
[HttpPost]
public IActionResult PerformCalculation()
{
}
However, this gives me an error:
InvalidOperationException: The AuthorizationPolicy named: 'ADD, SUB' was not found
The first thing to realize is that Authorize attribute Policy setting is singular unlike Roles which can be plural and that multiple policies are treated on an AND basis, unlike a list of roles which is treated on an OR basis.
In your example code “ADD, SUB” is considered a single policy name. If you want to attribute you method with both policies, your code should be as follows.
[Authorize(Policy = "ADD")]
[Authorize(Policy = "SUB")]
[HttpPost]
public IActionResult PerformCalculation()
{
}
However, this will not give you the effect you want of either or, since policies are AND together, hence both policies must pass to be authorized. Nor will the suggestions of writing a single policy or a requirements handler to handle the multiple requirements give you the result of treating policies on a OR basis.
Instead, the solution is to create a TypeFilterAttribute that accepts a list of policies and is tied to a IAsyncAuthorizationFilter that test for either or. The following outlines the two classes you will need to define and how to attribute your action method.
The following code defines the new attribute AuthorizeAnyPolicy class.
/// <summary>
/// Specifies that the class or method that this attribute is applied to requires
/// authorization based on user passing any one policy in the provided list of policies.
/// </summary>
public class AuthorizeAnyPolicyAttribute : TypeFilterAttribute
{
/// <summary>
/// Initializes a new instance of the AuthorizeAnyPolicyAttribute class.
/// </summary>
/// <param name="policies">A comma delimited list of policies that are allowed to access the resource.</param>
public AuthorizeAnyPolicyAttribute(string policies) : base(typeof(AuthorizeAnyPolicyFilter))
{
Arguments = new object[] { policies };
}
}
The following code defines the authorization filter class which loops through and executes each policy in the list. Should all the policies fail the result of the authorization context is set to forbid.
public class AuthorizeAnyPolicyFilter : IAsyncAuthorizationFilter
{
private readonly IAuthorizationService authorization;
public string Policies { get; private set; }
/// <summary>
/// Initializes a new instance of the AuthorizeAnyPolicyFilter class.
/// </summary>
/// <param name="policies">A comma delimited list of policies that are allowed to access the resource.</param>
/// <param name="authorization">The AuthorizationFilterContext.</param>
public AuthorizeAnyPolicyFilter(string policies, IAuthorizationService authorization)
{
Policies = policies;
this.authorization = authorization;
}
/// <summary>
/// Called early in the filter pipeline to confirm request is authorized.
/// </summary>
/// <param name="context">A context for authorization filters i.e. IAuthorizationFilter and IAsyncAuthorizationFilter implementations.</param>
/// <returns>Sets the context.Result to ForbidResult() if the user fails all of the policies listed.</returns>
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
var policies = Policies.Split(",").ToList();
// Loop through policies. User need only belong to one policy to be authorized.
foreach (var policy in policies)
{
var authorized = await authorization.AuthorizeAsync(context.HttpContext.User, policy);
if (authorized.Succeeded)
{
return;
}
}
context.Result = new ForbidResult();
return;
}
}
With the policies defined as shown in the question you would attribute the method as follows.
[AuthorizeAnyPolicy("ADD,SUB")]
[HttpPost]
public IActionResult PerformCalculation()
{
}
It’s that simple and you will find similar solutions in the following Stack Overflow questions.
Authorize against a list of policies
How to add multiple policies in action using Authorize attribute using identity 2.0?

autofac and owned instances

I have been reasing about owned instances and I have a need to set one up.
http://docs.autofac.org/en/latest/advanced/owned-instances.html
I have 2 methods in the same class that use this owned instance. I have set it up like this:
private readonly Func<SessionDetails, Owned<ITroposUnitOfWork>> _paramatizedTroposUnitOfWork;
My unit of work class constructor looks like this:
/// <summary>
/// Used for creating manual sessions
/// </summary>
/// <param name="sessionDetails">The details of the session to be created</param>
public TroposUnitOfWork(SessionDetails sessionDetails)
{
// Throw if we don't supply any details
ThrowIf.ArgumentIsNull(() => sessionDetails);
// Start the session
StartSession(sessionDetails);
}
So, my understanding is that if I use a using block, then the unit of work will be disposed of at the end of the call. But it isn't.
Like I mentioned before, I have 2 methods that use this owned instance. They are:
/// <summary>
/// Creates the Tropos user
/// </summary>
/// <param name="model">The user to be created</param>
/// <param name="password">The password to set</param>
private async Task CreateTroposUserAsync(User model, string password)
{
// If there is no password, throw an error
ThrowIf.ArgumentIsNull(() => password);
// Get our master user
var user = await base.FindByNameAsync(model.Master);
// If we have no master user, throw an error
if (user == null) throw new ObjectNotFoundException();
// Create our session details
var sessionDetails = _troposSession.Value.Create(user);
// User our new user
using (var troposUnitOfWork = _paramatizedTroposUnitOfWork(sessionDetails))
{
try
{
// Create our tropos user service
var userService = new TroposUserService(troposUnitOfWork.Value);
// Create our user
var transaction = userService.Create(model);
// Save our changes (Don't throw an error if the user already exists)
troposUnitOfWork.Value.RunTransaction(transaction);
} catch (Exception ex)
{
// Display human readable messages
throw new Exception(ex.Message);
}
}
// Sets the new users password
SetTroposPassword(model, password);
// Update the flag
model.HasTroposLogin = true;
}
And the other one is:
/// <summary>
/// Sets the tropos password
/// </summary>
/// <param name="model">The user that needs the password setting</param>
/// <param name="password"></param>
private void SetTroposPassword(User model, string password)
{
// Create our session details
var sessionDetails = _troposSession.Value.Create(model.UserName);
// Create our anonymous session
using (var troposUnitOfWork = _paramatizedTroposUnitOfWork(sessionDetails))
{
// Create our tropos user service
var userService = new TroposUserService(troposUnitOfWork.Value);
// Set our password
var transaction = userService.ChangePassword(password);
// Save our changes
troposUnitOfWork.Value.RunTransaction(transaction);
}
}
The first method does invoke the second method, but outside the using block. I put a breakpoint in the TroposUnitOfWork dispose method and it only gets hit once. The constructor is only hit once too.
Does anyone know why?
We need to see the initialization of _paramatizedTroposUnitOfWork.
What class has the CreateTroposUserAsync method? We need to see the constructor of that class. I suppose your overall goal is to get a unit of work implementation.
The reason why you only hit constructor once, might be due to the lifetime you used when registering. If its Owned. Then the two methods probably execute in the same lifetime scope and the dependency is only resolved once. Or put differently the _paramatizedTroposUnitOfWork(sessionDetails) returns the same instance.
I've solved similar problem using decorators and factories
public interface IEventHandlerFactory<in TNotification> where TNotification
: class, IAsyncNotification
{
IAsyncNotificationHandler<TNotification> Create( ILifetimeScope
lifetimeScope );
}
public class EventHandlerFactory<TNotification, TEventHandler> :
IEventHandlerFactory<TNotification>
where TNotification : class, IAsyncNotification
where TEventHandler : class, IAsyncNotificationHandler<TNotification>
{
public IAsyncNotificationHandler<TNotification> Create( ILifetimeScope
lifetimeScope )
{
return lifetimeScope.ResolveNamed<TEventHandler>( "EventHandler" )
as IAsyncNotificationHandler<TNotification>;
}
}
full .net fiddle is here https://dotnetfiddle.net/fw4IBw

Reference to an ASMX webservice wants to implement IDisposable

I have a somewhat simple web app, that uses an ASMX web service as its sole data access. All the information is gotten from it, and saved to it. It works fine so thats out of the way.
I just updated to VS2012, and it complained about the class implementing the service reference, does not inherit from IDisposeable.
After some reading, i am more confused as some solutions are really elaborate, some are simple. Short version is, after understanding so little, it seems like i cant adapt it to how my app is made.
I have several data access classes, all focusing on methods for an area. For example, one dataaccess for customer related calls, one for product related calls etc.
But since they are all using the same service, they all derive from a base data access class that holds the reference.
This is the base data access class:
public class BaseDataAccess
{
private dk.odknet.webudv.WebService1 _service;
private string _systemBrugerID, _systemPassword;
public BaseDataAccess()
{
//Gets the system user and password that is stored in the webconfig file. This means you only have to change
//the username and password in one place without having to change the code = its not hardcoded.
_systemBrugerID = System.Configuration.ConfigurationManager.AppSettings["SystemBrugerID"].ToString();
_systemPassword = System.Configuration.ConfigurationManager.AppSettings["SystemPassword"].ToString();
_service = new dk.odknet.webudv.WebService1();
}
/// <summary>
/// Gets an instance of the webservice.
/// </summary>
protected dk.odknet.webudv.WebService1 Service
{
get { return _service; }
}
/// <summary>
/// Gets the system user id, used for certain methods in the webservice.
/// </summary>
protected string SystemBrugerID
{
get { return _systemBrugerID; }
}
/// <summary>
/// Gets the system user password, used for certain methods in the webservice.
/// </summary>
protected string SystemPassword
{
get { return _systemPassword; }
}
}
And here is how a derived class utilizes the service reference from the base class:
public class CustomerDataAccess : BaseDataAccess
{
public CustomerDataAccess() {}
/// <summary>
/// Get's a single customer by their ID, as the type "Kunde".
/// </summary>
/// <param name="userId">The user's username.</param>
/// <param name="customerId">Customer's "fkKundeNr".</param>
/// <returns>Returns a single customer based on their ID, as the type "Kunde".</returns>
public dk.odknet.webudv.Kunde GetCustomerById(string userId, string customerId)
{
try
{
return Service.GetKunde(SystemBrugerID, SystemPassword, userId, customerId);
}
catch (Exception e)
{
Debug.WriteLine(e);
throw;
}
}}
So how on earth do i implement IDisposable in this situation? I just cant wrap my head around it.
EDIT
I have fiddled with the service reference, and come up with this:
/// <summary>
/// Gets an instance of the webservice.
/// </summary>
protected dk.odknet.webudv.WebService1 Service
{
get
{
try
{
using (_service = new dk.odknet.webudv.WebService1())
{
return _service;
}
}
catch (Exception e)
{
Debug.WriteLine(e);
throw;
}
}
}
Yes the exception handling isnt great, i will get to that (advice is appreciated), but VS2012 does not complain about the lack of IDisposable anymore.
Instantiation of the service has been removed from the constructor. The app works fine without any further modifications.
Will this suffice?

Reporting on code execution and design patterns?

First of all I wanted to thank all of you for your continuous contributions to the Stack Overflow community! I've been a member of Stack Overflow for years and have come to rely on your input more so than any other source online. Though I try to participate and answer members' questions whenever I can, every once in a while I find myself stuck and in need of help.
Speaking of which I have an unusual code problem. I am writing an API library in C# that needs to be able to be called from WPF/Windows Forms application, but also from within Unit Test code.
The issue is that I need to be able to report (in Excel) on whether each method of the library executed properly when the API is called from within a WPF/windows forms application, along some other metadata and optionally a return type.
When the code is consumed within Unit Tests I don't really care about the reporting, but I do need to be able to produce an Assert on whether the API call executed properly or not.
For instance, if in a Unit Test we have an Test Initialize portion, one of the API calls may be to create a Domain User for the test method to use. Another one may also create a Domain Group, so that the user has proper group membership.
To accomodate the consumption of the API from WPF/WinForms, I've been rewriting every function in the API to return a OperationStep type, with the hopes that when all API calls have executed I would have an IEnumerable<OperationStep> which I can write to a CSV file.
So the question is is there an easier way of achieving what I have done so far? The reporting is extremely tedious and time consuming to code, considering that the API library consists of hundreds of similar methods. Samples are described bellow:
OperationStep<PrincipalContext> createDomainConnectionStep = DomainContext.Current.GetPrincipalContext(settings.DomainInfo);
OperationStep<UserPrincipal> createDomainUserStep = DomainContext.Current.CreateUser(createDomainConnectionStep.Context, settings.TestAccountInfo.Username, settings.TestAccountInfo.Password);
OperationStep<GroupPrincipal> createDomainGroupStep = DomainContext.Current.CreateGroup(createDomainConnectionStep.Context, settings.TestAccountInfo.UserGrupName);
Where the DomainContext is a singleton object whose functionality is to connect to the domain controller and create a user, group, and associate the user to a group.
Note that both the second and the third method call require the output of the first, and therefore warranting the need for having the public T Context within the OperationResult object as described bellow.
The OperationStep object consists of the following properties which are inherited by the IOperation interface with the exception of the public T Context.
public class OperationStep<T> : IOperation
{
/// <summary>
/// Denotes the Logical Name of the current operation
/// </summary>
public string Name { get; set; }
/// <summary>
/// Denotes the stage of execution of the current operation: Setup, Execution, Validation, Cleanup
/// </summary>
public OperationStage Stage { get; set; }
/// <summary>
/// Denotes whether the test step completed properly or failed.
/// </summary>
public OperationResult Result { get; set; }
/// <summary>
/// Denotes the return type of the test method.
/// </summary>
public T Context { get; set; }
/// <summary>
/// Denotes any other relevant information about the test step
/// </summary>
public string Description { get; set; }
/// <summary>
/// If the test step result is failed, this should have the stack trace and the error message.
/// </summary>
public string Error { get; set; }
}
The method calls themselves are a bit bloated and tedious but here is a sample.
public class DomainContext
{
private static volatile DomainContext currentContext;
private static object synchronizationToken = new object();
/// <summary>
/// default ctor.
/// </summary>
private DomainContext() { }
/// <summary>
/// Retrieves the Current DomainContext instance.
/// </summary>
public static DomainContext Current
{
get
{
if (currentContext == null)
{
lock (synchronizationToken)
{
if (currentContext == null)
{
currentContext = new DomainContext();
}
}
}
return currentContext;
}
}
/// <summary>
/// Establishes a connection to the domain.
/// </summary>
/// <param name="domainInfo"></param>
/// <returns></returns>
public OperationStep<PrincipalContext> GetPrincipalContext(DomainInfo domainInfo)
{
OperationStep<PrincipalContext> result = new OperationStep<PrincipalContext>();
result.Name = "Establish Connection to Active Directory";
result.Result = OperationResult.Success;
result.Stage = OperationStage.Setup;
result.Description = string.Format("Domain Name: {0}, Default Containter: {1}", domainInfo.FQDN, domainInfo.Container);
try
{
ContextType contextType = this.GetContextType(domainInfo.DomainType);
PrincipalContext principalContext;
try
{
principalContext = new PrincipalContext(contextType, domainInfo.FQDN, domainInfo.Container);
}
catch
{
throw new Exception("Unable to establish connection to Active Directory with the specified connection options.");
}
if (principalContext != null)
{
bool authenticationResult = principalContext.ValidateCredentials(domainInfo.Username, domainInfo.Password);
if (!authenticationResult)
{
throw new Exception("Unable to authenticate domain admin user to Active Directory.");
}
result.Context = principalContext;
result.Result = OperationResult.Success;
}
}
catch(Exception ex)
{
result.Error = ex.Message;
result.Result = OperationResult.Failure;
}
return result;
}
}
When all method calls have executed theoreticaly I should have an IEnumerable<IOperation> which in the case of a win form I can write in a csv file (to be viewed in MS Excel) or in the case of a unit test I can simply omit the extra info and ignore (other than the method executed successively and the T Context property).
If I understood you correctly - all that OperationSteps are here only for logging. Then why not enable simple .NET logging? Log needed info where it is convenient for you. You can use TraceSource with DelimetedTraceListener to write to .csv file. More than that. You can move logging logic to Strategy class and override its logging methods in your unit test so that instead of logging you call Assert methods.

Categories

Resources