I have a couple of reliable collections across different stateful services. I need to access one reliable collection from another stateful service (e.g. Employees collection from Department stateful service).
Although the Employees collection is populated with data, when I try to get a reference to the collection
var myDictionary = await this.StateManager.GetOrAddAsync>("employees");
var allEmployees = await mydictionary.CreateEnumerableAsync(tx, EnumerationMode.Unordered)
var enum = allEmployees.GetAsyncEnumerator()
the enumeration count on allEmployees collection returns count of 0.
The same approach works correctly when I try to access the employees in Employee collection in the Employee stateful service.
This doesnt work when I try to access the employees in Employee collection in the Department stateful service.
Is this a correct way to access data across collections? If not what is the correct way?
A stateful service contains it's own state that can be accessed only with that service, it can't be shared with another stateful service. Don't think of it as a database. Each stateful service can contain multiple collections or queues, but that service owns that state. If you want to expose it, create an API using your favorite communication stack and make an API call from the other service.
Related
Note: This is a security related question.
I am putting users in groups, which the name are moderately sensitive (database object ids).
I am sending messages to groups from the server side, never from client (that's why putting db object ids in the group's names was not a problem for me).
From my understanding, I am assuming that SignalR is managing groups deep inside its core, and communicate only with each Connections, but I am not sure.
So my questions are:
Does the groups name are well hidden from client?
Or is it possible for a User (from the client side), to discover in which Group(s) he belongs to? (and then potentially discover sensitive data if developer was assuming groups names where hidden/inaccessible)
Group names would only be exposed if you passed them to the client.
From the server side, SignalR has no API to maintain or expose this. You can maintain your own group names, thus any exposure would come from your own doing.
As far as security goes, that should be handled outside of SignalR.
You can however check out using roles to help if you need to restrict on specific methods such as (link):
[Authorize(Roles = "Admin")]
public class AdminAuthHub : Hub
{
}
I read some documentation about using a in memory store for a SignalR app.
http://www.asp.net/signalr/overview/guide-to-the-api/mapping-users-to- connections#inmemory
I believe you can use a Static Collection to hold your objects you need to process within the hub. Is it possible to have access to this Static collection from outside the hub? If you have other objects within the app who need access to this in memory store what is the best practise?
Best practice is to let the Hub act only as a Hub, no business logic of any kind. Also dont call the hub client methods from your core logic classes, this is highly coupled and is bad practice. Abstract the Hub either with your own code or use a library, I have created this abstraction library that is based on the Event aggregation pattern.
http://andersmalmgren.com/2014/05/27/client-server-event-aggregation-with-signalr/
Just make the Static collection public and access it like any other Static collections. The collection will be lost when the app closes so would need to be stored persisted somewhere is needed.
I have created a simple order manager wf service (state machine) in WF4.
Order (EF entity) properties: Id, IsExport, NumOfProduct, ProductName, Status (waiting, approved, rejected).
State machine states:
1. OrderReceived (validation -> response activity)
2. Waiting (empty)
- Transitions:
update(update order activity) -> waiting state
approve(assign status field, update order and response activities) -> final state
3. Final state.
Correlation key: Order.Id
The implementation rised a few questions.
WF can manage one flow of the order instance, the order flow and the order entity is in one-one relation.
Question is that where and how should I implement the listing of entityes according to a state filter (eg. approved orders or waiting orders). The list should be accessible via WCF service method.
What is the best practise to manage the batch data processing. (eg: Multiple order approval. "Foreach" in the client is not the required sln.)
The state of the order is symbolized by the "state activity persisted instances" and the entity's status field in the db as well.
What is the best practise to decide the state of the entity, listing the active persisted activity instances in the defined state or select the entities from the db (by an activity) according to a state filter parameter?
Any help would be appreciated.
Good questions!
Taking your first and third questions, there are several possible approaches to this. All require that you write a custom WCF service to enumerate the required orders. This would probably not be a WF service; it might be a REST or OData service. How would you implement the service?
You could do it entirely by querying your database through EF. This would have no dependency on WF at all, and is probably the easiest way. Your workflow would update the database record on each state change, and the service would only need to read that value.
You could rely on the tracking mechanism provided by WF, and the extensions that Ron Jacobs refers to in his answer to your question. The tracking infrastructure is described here on MSDN. It is possible to use the tracking object in memory to get the state of active workflows. However, this probably won't work well with IIS/WF services, which are automatically persisted and unloaded when dormant. You would be better off using the tracking facilities to write state records to a database. Your custom service would then just query this tracking database.
Unless you want comprehensive information about the state changes and updates that have occurred through your WF service, suggestion number one should suffice.
As for your second question, that is a little more complicated. Let's say you write a REST service that lists the orders awaiting approval. You write a Web page that displays those orders, and the user can check the orders he wants to approve. Now, the number of workflows that you need to update is the same as the number of orders he approves.
You could, as you mention, call the Web service multiple times—but for a large number of orders that would be an unnecessary overhead.
What's the alternative? You would need to write a custom service method on your non-WF service that takes an array of order ids. That service would have to call your WF service multiple times to update each one. Since the WF service is being called from another service on the same machine, you can use the .Net Named Pipe binding instead of one of the HTTP bindings so that the overhead is much less.
It's worth noting that Entity Framework doesn't support batched updates either. You'd need to write a stored procedure or custom SQL if you wanted the database update to be batched too.
Is all of this worth the effort? Probably! Using WCF and the named pipes binding is pretty standard with WF. You'll need to configure Windows Activation Service for named pipes. Also, if you're not already using AppFabric for Windows Server, have a look into it, because it adds some very good management tools for WF services.
I recently published some new samples to show how you can access the current state of the StateMachine and possible transitions. These might help you.
Windows Workflow Foundation (WF4) - Tracking State Machine Workflow Service
Windows Workflow Foundation (WF4) - Tracking State Machine
Our company has a multi tenant asp.net web application. The application is 3 tier e.g. website,business and dataaccess. We hold the tenant id in session after the user logs in.
When we need to get a list of 'customers or orders' we pass the tenant id from the website to the business to the data access and then to the database (and query for customers or orders for that tenant). (almost every business function takes tenantId as a parameter)
Sometimes when creating new functions developers forget to add the tenant id from the website to the database, causing a security issue.
Is there a way we could do this so that the developers dont need to always remember to pass the tenant id.
Any suggestions on how best to resolve this issue.
public class CommonService
{
public int getTenantId()
{
//do your validations and error handlings
string tid = session["tenantId"] // or get it from customs claims principal or set it in a httpcontext.current.items
return tid;
}
}
Then use the service in every business object to get the tenant id and pass it to the data layer without depending on the developers to do it. Its a very big security hole, missing an tenantId might return data which the user is not supposed to see and might shutdown the company
It sounds like you are passing all the values around individually.
If you construct an object that you can pass around freely, you will always have the information you need. I would assume that the UserId is always associated with a tenant. Can you build a simple object, store it in the session and then pass it to all functions needing it.
class user{
int userID;
int tenantID;
}
If you have a value in the Session and you need it in the database queries, you have to propagate it through the tiers to the database queries.
If your developers sometimes forget to pass the value and they get security issues, that is actually not a security issue but a security feature.
If the database needs that id, then the business layer methods should have parameters for it. How can they forget it?
One approach would be to create a View per table per tenant (may not be practical depending on the number of tenants you have and how frequently they change) and deny access to the application to the underlying tables.
This article explains how to do this as well as several other approaches and their performance tradeoffs:
http://msdn.microsoft.com/en-us/library/aa479086.aspx
UserList userList = (UserList) Component.getInstance(UserList.class);
return userList.getUserByLoginId(loginId);
A sample code usage of fetching a user by login id is given below. I instantiate the UserList class to call the method. What ScopeType should I use here specifically so that the object's scope is minimal.
If you want to access authenticated users via your UserList object you must keep it in application scope. But, it is alive during the entire application life. So, it is not minimal.
Another approach may store logged-in users in a database table and you can query this table via an event scoped component. Event scope is equivalent of Http's "request" scope. So, it is killed after each server request.