Should I consider following code as thread safe? - c#

I have following POCO class.
public class SessionInfo
{
public int UserID { get; set; }
public string UserName { get; set; }
public string Name { get; set; }
public List<Role> UserRoles { get; set; }
public List<Permission> Permissions { get; set; }
}
and SessionService class as below:
public static class SessionService
{
static string userName;
static int userID;
static List<Role> RoleList;
public static SessionInfo SetServiceSession<T>(T service) where T : class
{
SessionInfo sessionInfo;
SetApiControllerSessionValue();
sessionInfo = new SessionInfo { UserID = userID, UserName = userName, UserRoles = RoleList, Name = null, Permissions = null };
//above statement fills the value set by SetApiControllerSessionValue into the sessionInfo object and returns.
return sessionInfo;
}
private static void SetApiControllerSessionValue()
{
.....
.....
//Here is some logic that sets the static member `userName`, `userId` and `RoleList` of `SessionService` class
.....
.....
}
}
Now I am calling SetServiceSession method from every action of every api controller like below:
public class TestController : ApiController
{
public List<TestPOCO> Get()
{
.....
.....
TestService service = new TestService(uow);
SessionInfo = SessionService.SetManagerSession<TestService>(service);
.....
.....
.....
}
.....
.....
// Same way for post, create and delete.
.....
.....
}
Now if server is processing simultaneously two request let's say Get and Post for two different session, SessionService.SetManagerSession will be executed in parallel. So question is can it be resulted in invalid session Values (exchanged static values in two requests) as it is being executed in parallel? If yes what is the solution for that?
Also correct me if my understanding about above code is wrong.
Thanks in advance.

Should I consider following code as thread safe?
No, obviously not. If SetServiceSession is concurrently in multiple threads, userName, userID etc fields will be messed up.
If yes what is the solution for that?
There are only two options.
Don't use a shared state.
Use proper synchronization.
I prefer option 1. In this case you can completely get rid of that static members and make the SetApiControllerSessionValue to return a SessionInfo. Of course, rename the method as GetApiControllerSessionValue.
public static SessionInfo SetServiceSession<T>(T service) where T : class
{
SessionInfo sessionInfo = GetApiControllerSessionValue();
//Do something with sessionInfo, if needed
return sessionInfo;
}
private static SessionInfo GetApiControllerSessionValue()
{
//Get SessionInfo here.
//If you need to access any other shared state here, you must need synchronization.
}
For more information about synchronization primitives refer this. If you want me to provide a specific answer than a generic one as above, post your original code.

Related

DDD modelling of articles, variants and their parameters

I am learning DDD and trying to model articles, its variants and parameters.
Article can be on it's own without variants
Variant must be child of an article
both article and variant can have some parameters (colors, brands, sizes...), physical quantities (width, length, some article-specific like inner length)
If you set some parameter on an article, it can be "synchronized" to it's children variants
you can override this in a variant by setting that parameter as "unlinked", then this variant would have different parameter value than article
some parameters can be set multiple times (color: red, blue), but some only once (brand)
those parameters are dynamically create, it's not a Color or Brand property but key-value selected from preconfigured values
I think my main aggregate roots will be Article and Variant.
My current code looks like this:
internal class Article : AggregateRoot<ArticleId>
{
private readonly ISet<VariantId> _variants = new HashSet<VariantId>();
private readonly ISet<AssignedParameter> _parameters = new HashSet<AssignedParameter>();
private readonly ISet<AssignedPhysicalQuantity> _physicalQuantities = new HashSet<AssignedPhysicalQuantity>();
public string Name { get; private set; }
public string Catalog { get; private set; }
public IReadOnlySet<VariantId> Variants => _variants.AsReadOnly();
public IReadOnlySet<AssignedParameter> Parameters => _parameters.AsReadOnly();
public IReadOnlySet<AssignedPhysicalQuantity> PhysicalQuantities => _physicalQuantities.AsReadOnly();
private Article(ArticleId id, string name, string catalog)
: base(id)
{
Name = name;
Catalog = catalog;
}
public static Article Register(ArticleId id, string name, string catalog)
{
var article = new Article(id, name, catalog);
article.AddEvent(new ArticleRegistered(article.Id, article.Name, article.Catalog));
return article;
}
public void AssignParameter(Parameter parameter, ParameterValue parameterValue, bool syncToVariants)
{
if (!parameter.CanBeAssignedMultipleTimes && _parameters.Any(p => p.ParameterId == parameter.Id))
{
throw new ParameterCanBeAssignedOnlyOnceException($"Parameter {parameter.Id} can by assigned only once.");
}
var assignedParameter = new AssignedParameter(parameter.Id, parameterValue.Id, syncToVariants);
if (!_parameters.Add(assignedParameter))
{
throw new ParameterIsAlreadyAssignedException($"Parameter {parameter.Id} with value {parameterValue.Id} is already assigned.");
}
AddEvent(new ArticleParameterAssigned(Id, assignedParameter.ParameterId, assignedParameter.ParameterValueId));
}
public void UnassignParameter(Parameter parameter, ParameterValue parameterValue)
{
var assignedParameter = _parameters.FirstOrDefault(p => p.ParameterId == parameter.Id && p.ParameterValueId == parameterValue.Id);
if (assignedParameter is null)
{
throw new ParameterIsNotAssignedException($"Parameter {parameter.Id} is not assigned.");
}
_parameters.Remove(assignedParameter);
AddEvent(new ArticleParameterUnassigned(Id, assignedParameter.ParameterId, assignedParameter.ParameterValueId));
}
// physical quantity assign / unassign are similar to parameters
}
internal class Variant : AggregateRoot<VariantId>
{
private readonly ISet<AssignedParameter> _parameters = new HashSet<AssignedParameter>();
private readonly ISet<AssignedPhysicalQuantity> _physicalQuantities = new HashSet<AssignedPhysicalQuantity>();
public string Name { get; private set; }
public string Catalog { get; private set; }
public EanCode Ean { get; private set; }
public decimal Weight { get; private set; }
public IReadOnlySet<AssignedParameter> Parameters => _parameters.AsReadOnly();
public IReadOnlySet<AssignedPhysicalQuantity> PhysicalQuantities => _physicalQuantities.AsReadOnly();
internal Variant(VariantId id, string name, string catalog, EanCode ean, decimal weight)
: base(id)
{
Name = name;
Catalog = catalog;
Ean = ean;
Weight = weight;
}
// parameter and physical quantity assignment methods
}
Parameters:
internal class Parameter : AggregateRoot<ParameterId>
{
private readonly ISet<ParameterValue> _values = new HashSet<ParameterValue>();
public string Code { get; private set; }
public string Name { get; private set; }
public bool CanBeAssignedMultipleTimes { get; private set; }
public IReadOnlySet<ParameterValue> Values => _values.AsReadOnly();
public Parameter(ParameterId id, string code, string name, bool canBeAssignedMultipleTimes)
: base(id)
{
Code = code;
Name = name;
CanBeAssignedMultipleTimes = canBeAssignedMultipleTimes;
}
}
internal class ParameterValue : Entity<ParameterValueId>
{
public string Code { get; private set; }
public string Name { get; private set; }
public Parameter Parameter { get; private init; } = null!;
public ParameterValue(ParameterValueId id, string code, string name)
: base(id)
{
Code = code;
Name = name;
}
}
Value objects:
// for Article, variant doesn't have SyncToVariants property and has some other
internal class AssignedParameter : ValueObject
{
public ParameterId ParameterId { get; private init; }
public ParameterValueId ParameterValueId { get; private init; }
public bool SyncToVariants { get; private init; }
public AssignedParameter(ParameterId parameterId, ParameterValueId parameterValueId, bool syncToVariants)
{
ParameterId = parameterId;
ParameterValueId = parameterValueId;
SyncToVariants = syncToVariants;
}
protected override IEnumerable<object> GetEqualityComponents()
{
yield return ParameterId;
yield return ParameterValueId;
}
}
internal class AssignedPhysicalQuantity : ValueObject { ... }
My questions:
What would be the best way to notify variants of the parameter change? I can think of two ways using events.
First would be using ArticleParameterChanged(ArticleId, parameter.Id, parameterValue.Id). I would handle this event and changed all variants at once in the handler - I don't think this is the way, but I wouldn't need to hold variants collection in article.
Second would be to loop through variant IDs and create ArticleVariantParameterChanged(ArticleId, VariantId, parameterId, parameterValueId) event. This seems more correct to me?
if (syncToVariants)
{
foreach (var variantId in _variants)
{
AddEvent(new ArticleVariantParameterChanged(Id, variantId, parameter.Id, parameterValue.Id);
}
}
How do I add new variant to article? The easiest way would be to create new variant and update the article in one transaction.
// Article method
public Variant RegisterVariant(VariantId variantId, ...)
{
var variant = new Variant(variantId, ...);
_variants.Add(variantId);
return variant;
}
// command handler? or domain service?
var article = await _articleRepo.GetAsync(articleId);
var variant = article.RegisterVariant(variantId, ...);
await _variantRepo.AddAsync(variant);
await _articleRepo.UpdateAsync(article);
Or using events?
// Article method
public Variant RegisterVariant(VariantId variantId, ...)
{
var variant = Variant.Register(variantId, this.Id, ...);
return variant;
}
// Variant static method
public Variant Register(VariantId variantId, ArticleId articleId, ...)
{
var variant = new Variant(variantId, articleId, ...);
variant.AddEvent(new VariantRegistered(variantId, articleId));
return variant;
}
// command handler
var variant = article.RegisterVariant(...);
await _variantRepo.AddAsync(variant);
// VariantRegisteredHandler
article.AddVariant(variantId);
However here it seems kind of confusing to me, article.RegisterVariant and article.AddVariant... Maybe it's just wrong naming?
Also here can occur condition race between adding new variant and assigning a new parameter, when someone adds new parameter before the VariantRegistered event was handled, so it wouldn't sync that parameter.
So I'm thinking, is it even good idea to store those shared parameters in each variant? Maybe it would be enough to just have variant specific parameters there and merge everything in the read model? However this would be harder to prevent duplications - if the article already has a parameter "color - red", assigning "color - red" to variant would need to check the article parameters too and there can be another race condition.
I read that entities without any domain business logic could be treated as CRUD, that means they wouldn't even inherit AggregateRoot and each of them would have own repository, right?
Let's say someone really wants to delete some parameter value, for example blue color. This wouldn't (hopefully) happen in my app, but I'm still curious how this would be handled. He confirms he really wants to delete it and I need to go through all articles and unassign it from them. How?
My idea would be either to have ParameterValueDeleted event and ParameterValueDeletedHandler would query for all articles and variants and unassign it one by one, this handler would take really long time to execute.
Or ParameterValueDeletedHandler would query for all IDs, create some event for them and that handler would unassign it later. However in the latter case I don't know how that event would be named to make sense. UnassignArticleParameter seems more like command than event and ArticleParameterUnassigned is something coming from article. Also I read that commands indicate something that can be rejected, so I would say command doesn't fit here.
Also I see a problem when someone deletes that parameter and someone else queries for an article which doesn't have it unassigned yet - database join would fail because it would join to non existent parameter (considering single database for read and write model).
If I wanted to have mandatory parameters, where would be the best place to validate that all of them are set? Move the article registration logic to ArticleFactory and check it there? And for variants maybe ArticleService or VariantFactory? This seems kinda inconsistent to me, but maybe it's right?
var article = await _articleRepo.GetAsync(articleId);
_articleService.RegisterVariant(article, /* variant creation data */);
_variantFactory.Register(article, /* variant creation data */);
I think this should be all, I hope I explained everything well.
I would appreciate any help with this!

Fluxor Blazor how to save a List?

I am developing a Blazor app and in this app, I need to store the state of a List of user-selected Items.
when the user presses the 'Save Changes' button I would like to store the list in the state.
So far I have written the four mandatory classes that are written in the Fluxor doc:
ServiceState:
public record ServiceState
{
public List<ServiceModel> SelectedService { get; init; }
}
ServiceFeature
public override string GetName() => nameof(ServiceState);
protected override ServiceState GetInitialState()
{
return new ServiceState
{
SelectedService = new List<ServiceModel>()
};
}
SelectServiceAction:
public class SelectServiceAction
{
public List<ServiceModel> _serviceList;
public SelectServiceAction(List<ServiceModel> choosenServices)
{
_serviceList = choosenServices;
}
}
and SelectServiceReducer:
public class SelectServiceReducer
{
[ReducerMethod]
public static ServiceState OnSelectService(ServiceState state, SelectServiceAction action)
{
return state with
{
SelectedService = action._serviceList
};
}
}
I have tried many things and nothing seems to work the List stored in the state appears always empty
but the funny thing is that in the SelectServiceAction class:
public SelectServiceAction(List<ServiceModel> choosenServices)
{
_serviceList = choosenServices;
}
if I put a breakpoint in the last } _serviceList contains correctly all the items that were contained in the list I passed to the dispatcher. It seems like the problem is in the ServiceState itself,
Do you happen to know what am I doing wrong?
If you need me to show more code, I will post it
I thank you kindly in advance.
I found a way to do this. I don't know if this is the best way but here we are.
Your SelectServiceAction should have a ServiceModel in the constructor. I also changed the name of your method. I think its good to place the verb in the method name because you're likely to have a remove as well.
public class SelectServiceAddAction
{
public ServiceModel _service {get; set; }
public SelectServiceAddAction(ServiceModel service)
{
_service = service;
}
}
then in your reducer you call the method.
public static class SelectServiceReducer
{
[ReducerMethod]
public static ServiceState OnSelectService(ServiceState state, SelectServiceAddAction action)
{
var SelectedService = state.SelectedService;
SelectedService.Add(action._service);
return state with
{
SelectedService = SelectedService
};
}
}
Also consider changing "SelectedService" to a name that involves the state such as "CurrentSelectedServices" hope this helps!

Passing a class object that only PostSharp can see

I'm not sure if this is possible or not.
I have a method call from client api to service api (two separate projects in two separate locations) that I want post sharp to intercept. Calls are from the client and postsharp is on the service
service.GetLogin(username)
The key here is I need to pass an authorization object that will show in the postsharp onentry method
public class Authorization
{
public string client_id { get; set; }
public string client_secret { get; set; }
public string access_token { get; set; }
public string token_type { get; set; }
public string expires_in { get; set; }
}
var auth = new Authorization();
auth.client_id = "xyz";
auth.client_secret = "abc"
and in postsharp
[Serializable]
public class LoggingAspect : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
//I need the object to show up here
}
}
Problem:
I do not want to pass this object in every single method call as I have over 1000 methods. Is there a way to attach that authorization object to each call so that postsharp can see it without doing something like this
service.GetLogin(username, auth);
service.Foo(auth)
service.Bar(auth);
service.xyz(auth);
services.abc(auth);
Can you imagine adding just this one object to over 1000 methods?
PostSharp is unable to directly consume data from call sites, as it would require adding an actual parameter to the method (or emitting a new overload). This is in theory possible with the low-level SDK, but would be hard to maintain and costly to implement.
The best way to achieve this is to use AsyncLocal<T> which allows you to store data in the ExecutionContext.
public class AuthorizationProvider
{
private static AsyncLocal<Authorization> state = new AsyncLocal<Authorization>();
public Authorization Current { get => state.Value; set => state.Value = value; }
}
Code, where authorization is valid, will be:
Authorization authorization = ... ;
try
{
AuthorizationProvider.Current = authorization;
// your logic.
}
finally
{
AuthorizationProvider.Current = null;
}
Then you can read the authorization object from OnEntry:
[Serializable]
public class LoggingAspect : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
if (!(AuthorizationProvider.Current?.IsValid ?? false))
{
...
}
}
}
You can also wrap the setting/unsetting of the current Authorization in an IDisposable so that you can use using statement.
Values set assigned in the AsyncLocal are stored in the execution context and as such flow through async calls. The value stored in the execution context which may be captured and used after you remove the value in the finally block above. See more here.

Is it correct way to store and retrive session in asp.net

I want to make a class to retrieve data from session state, am doing as following is it correct way?
I have make a static class and static methods to get data
[AuthorizeMember]
public class TestController : Controller
{
public ActionResult list()
{
Session["memberid"] = 12345;
return View();
}
public ActionResult iteminfo(string prodcode)
{
int memberid=SessionData.MemberTableId();
}
}
public static class SessionData
{
public static int MemberTableId()
{
return Convert.ToInt32(HttpContext.Current.Session[memberid]);
}
}
Static class will serve same contents on all logged in sessions.
Avoid using static classes in web application unless you completely understand how it is going to work.
Option 1:
You can either directly put values in session as shown in your code sample.
The advantage is you dont need to write any wrapper.
The disadvantage is anybody will keep on adding any value to session and after your application grows, nobody will know which data you are keeping in session.
Option 2:
OR you can create a single class to hold all session values together.
Whenever you want to read session value always read from this class.
Mark this class as serializable, so that in future, if you want to keep your session state in SQL Server or on some other server like REDIS cache, then it would just be minimal configuration change.
That way you will always know what all values you put in the session.
For ex. You can have a class to hold all your session values
[Serializable] //// This is required when using out of proc session state
public class MySessionState
{
public string Username {get; set;}
public string Role {get; set;}
public string FirstName{get; set;}
public string LastName {get; set;}
public int Age{get; set;}
}
Create a const key to refer this class object
public const string MySessionObjectKey = "mysessionstate";
Then in your controller actions you can use it like this:
public void MyAction()
{
var sessionState = Session[MySessionObject] as MySessionState;
if (sessionState == null)
{
sessionState = new MySessionState();
}
sessionState.FirstName = "SomeName";
sessionState.LastName = "SomeOtherName";
/// Process this session object
Session[MySessionObjectKey] = sessionState;
}
Hope this helps you.

Can ServiceStack services contain multiple methods?

Environment is Visual Studio 2012, ServiceStack, ASP.NET Web Application Project (followed https://github.com/ServiceStack/ServiceStack/wiki/Create-your-first-webservice)
Looking through some of the classes in ServiceStack.Examples, I noticed that most of the services contain only one method. Either some override on Execute() or, if a REST service, some override of OnPost/Get/Put/Delete().
How should I approach making a full API set, if I have tens of functions I need implemented RegisterUser(), RemoveUser(), AddFriend(), RemoveFriend() ... One service per method?
public RegisterUserService : IService<User> { public object Execute(User> dto) { ... } }
public RemoveUserService : IService<User> { public object Execute(User> dto) { ... } }
public AddFriendService : IService<Friend> { public object Execute(Friend dto) { ... } }
public RemoveFriendService: IService<RequestDTO4> { public object Execute(Friend dto) { ... } }
I'm pretty lost on how to begin implementing a full API set. I've read the first and second wiki page on 'Creating your first webservice', which I've copied to make 1 service method. But now I want to make 10 or 40 service methods and I'm not sure how to do that.
I noticed that implementing from IRestService<T> allows you up to 4 methods instead of the one Execute() method, simply because each method corresponds to a different HTTP verb. So is there something like that I could write? Basically something like:
public MyService : IService/IRestService/ServiceBase?<User>
{
public object AddUser(User user) { }
public object RemoveUser(User user) { }
public object ModifyUser(User user) { }
}
Just looking for something that doesn't necessarily have to contain all methods in one service class, but as many as reasonably possible ... do I really have to create 1 service for each service method?
Note on pursuing a strictly RESTful architecture: I only read up a little on REST, but it seems like I'd have to strictly follow rules like: treat everything as a resource even if you have to re-design your models, no verbs in the URL names (/Friends, not /GetFriends because REST gives you OnGet(), OnPost(), OnPut(), and OnDelete() ... basically I'm interested in the easiest, quickest, and most painless way of implementing a a few dozen service methods. It's a personal project, so the requirements won't vary too much.
Thanks in advance for guiding me through this first step.
EDIT: Just saw this related question: How to send commands using ServiceStack?
Mythz said there's no "ServiceStack way" to design. The guy's question is pretty much like mine. I'm wondering how to stack a lot of service methods in a service.
EDIT 2: Just saw Need help on servicestack implementation, and Separate or combined ServiceStack services?.
I just tested the code below successfully with working routes:
[Route("/registerUser/setEmail/{Email}")]
[Route("/registerUser/setPassword/{Password}")]
[Route("/registerUser/setPhoneNumber/{PhoneNumber}")]
[Route("/lalal2395823")]
[Route("/test3234/test23423511")]
public class RegisterUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Nickname { get; set; }
public string PhoneNumber { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
But what I'd like is for each [Route("path")] to go to a different method, instead of having them all parsed in Execute() and having to parse which string isn't null or empty.
My Solution
I decided to take Rickard's advice and make a proper REST API, because it seems simpler and cleaner in the end.
This is now my class using the new ServiceStack API (new as of 9/24/12):
using UserModel = Project.Model.Entities.User;
[Route("/User", "POST")]
[Route("/User/{FirstName}", "POST")]
[Route("/User/{FirstName}/{LastName}", "POST")]
[Route("/User/{FirstName}/{LastName}/{Nickname}", "POST")]
[Route("/User/{FirstName}/{LastName}/{Nickname}/{PhoneNumber}", "POST")]
[Route("/User/{FirstName}/{LastName}/{Nickname}/{PhoneNumber}/{Email}", "POST")]
public class CreateUser : IReturn<UserModel>
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Nickname { get; set; }
public string PhoneNumber { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
public class CreateUserService : Service
{
public object Post(CreateUser request)
{
try
{
using (var session = FluentNHibernateHelper.OpenSession())
{
using (var transaction = session.BeginTransaction())
{
var user = new UserModel()
{
FirstName = request.FirstName,
LastName = request.LastName,
Nickname = request.Nickname,
PhoneNumber = request.PhoneNumber,
Email = request.Email,
Password = request.Password,
};
session.SaveOrUpdate(user);
transaction.Commit();
return user;
}
}
}
catch
{
throw;
}
}
}
This is now a lot simpler with ServiceStack's new API Design released in (v3.9.15+).
#Rickard makes a lot of good points on how to re-structure your service so it's more REST-ful which is now easier to achieve with ServiceStack's new API which is now less restrictive and more flexible where the same service can handle multiple different Request DTOs and you're no longer restricted in the Response Type you can return.
Following the HTTP way you have to turn your way of thinking upside down. You need to think in terms of resources, i.e. users, friends, etc. Using HTTP you already have a finite set of methods, namely Get, Put, Post, and Delete.
Hence, the service API design could look like this:
RegisterUser() => POST /users
RemoveUser() => DELETE /users/{userid}
AddFriend() => POST /users/{userid}/friends
RemoveFriend() => DELETE /users/{userid}/friends/{friendid}
ModifyUser() => PUT /users/{userid}
etc.
To implement for example RemoveFriend in ServiceStack you could do like this:
public class UserFriendService : RestServiceBase<UserFriendRequest>
{
public override object OnPost(UserFriendRequest request)
{
// pseudo code
var user = GetUser(request.UserId);
var friend = GetUser(request.FriendId); // FriendId is a field in the HTTP body
user.Friends.Add(friend);
return HttpResult.Status201Created(user, ...);
}
//...
}
[Route("/users/{userId}/friends")]
public class UserFriendRequest
{
public string UserId { get; set; }
public string FriendId { get; set; }
}

Categories

Resources