Background
I'm building a two-tiered C# .net application:
Tier 1: Winforms client application using the MVP (Model-View-Presenter) design pattern.
Tier 2: WebAPI RESTful service sitting on top of Entity Framework and SQL Server.
If you would like more detail on the application I'm building, I gave a probably too thorough explanation here.
Current Development
Currently, I'm working on the Winforms client. Particularly, I'm trying to hash out a adequate implementation of the command pattern within this client. I was fortunate enough to stumble across this excellent blog post that outlines a solid command architecture. To complement that post, the author followed up by explaining how he separates queries from commands. After reading those blogs, it becomes very clear that my tier 2 (web api service) would greatly benefit from implementing both of these. The generic implementation allows for fantastic flexibility, testability, and extensibility.
Question
What is less clear to me is how I go about implementing these patterns on the winforms client side of things (tier 1). Do queries and commands continue to be considered separate here? Consider a basic action, such as a login attempt. Is that a query or a command? Ultimately, you need data back (user information on the server) from the web service, so that would make me think it is a query. What about another case, such as a request to create a new user. I understand that you would create a command object that stores the user information and send that off to the service. Commands are supposed to be fire and forget, but wouldn't you want some sort of confirmation from the service that the command was successful? Furthermore, if a command handler returns void, how would you tell the presenter whether or not the user creation request was successful?
At the end of the day, for any given UI task (say the user creation request), does it end up that you end up having a winforms client based query/command, as well as a web api service version of the command/query which handles the request on that end?
Do queries and commands continue to be considered separate here?
Yes, typically you would fire a command and if you need to update the UI after this action has been performed you would perform a query to get the new information. An example will make this clear.
Let's say you would assign a specific guard to a certain area. The only information the command (which is only a DTO) needs is the Id of the guard and the Id of the area. The associated CommandHandler will perform all tasks to handle this, e.g. removing that guard from another area, booking him as unavailable etc.
Now your UI would want to show the change. The UI has probably some kind of list with all guards and their assigned area. This list will be populated by a single GetActiveGuardsAndAreaQuery which will return a List<GuardWithAreaInformationDto>. This DTO could contain all kinds of information about all guards. Returning this information from the command is not a clean separation of concerns, because the atomic command handling could be very well used from a similar but slightly different UI, which will require a slightly different update of the UI information.
such as a login attempt. Is that a query or a command?
IMO a login attempt is neither. It is a cross cutting concern, an implementation detail that the data is hidden behind a secure connection. The application however should not be concerned with this detail. Consider using the application with another customer where you could host the WebApi service in and Active Directory domain where you can use Windows Authentication. In that case the user only has to login to his machine and the security is handled by the client and server OS while communicating.
With the patterns you're referring to this can be nicely done using a AuthenticateToWebApiServiceCommandHandlerDecorator which makes sure their are login credentials to serve to the service by asking the user in a modal form, reading it from a config file, or whatever.
Checking if the credentials worked can be done by performing a kind of a standard Query your application always needs such as CheckIfUpdateIsAvailableQuery. If the query succeeds the login attempt succeeded otherwise it failed.
if a command handler returns void, how would you tell the presenter whether or not the user creation request was successful?
While it seems that void doesn't return anything this is not really true. Because if it doesn't fail with some exception (with a clear message what went wrong!) it must have succeeded.
In a follow up of the mentioned blog posts #dotnetjunkie describes a way to return information from commands but make notice of the added comment on the top of post.
To summarize, throw clear exceptions from failed commands. You can add an extra layer of abstraction client side to handle this nicely. Instead of injecting a commandhandler directly into the different presenters you can inject an IPromptableCommandHandler which has only one open generic implementation at compile time:
public interface IPromptableCommandHandler<TCommand>
{
void Handle(TCommand command, Action succesAction);
}
public class PromptableCommandHandler<TCommand> : IPromptableCommandHandler<TCommand>
{
private readonly ICommandHandler<TCommand> commandHandler;
public PromptableCommandHandler(ICommandHandler<TCommand> commandHandler)
{
this.commandHandler = commandHandler;
}
public void Handle(TCommand command, Action succesAction)
{
try
{
this.commandHandler.Handle(command);
succesAction.Invoke();
}
catch (Exception)
{
MessageBox.Show("An error occured, please try again.");
// possible other actions like logging
}
}
}
// use as:
public void SetGuardActive(Guid guardId)
{
this.promptableCommandHandler.Handle(new SetGuardActiveCommand(guardId),() =>
this.RefreshGuardsList());
}
At the end of the day, for any given UI task (say the user creation request), does it end up that you end up having a winforms client based query/command, as well as a web api service version of the command/query which handles the request on that end?
No!
Client side you should create a single open generic CommandHandlerProxy which solely task is to pass the command dto to the WebApi service.
For the service side architecture you should read another follow up: Writing Highly Maintainable WCF Services which describes an server side architecture to handle this very nicely. The linked project also contains an implementation for WebApi!
Related
I'm new in DDD/ Clean Architecture
I'm trying to implement this architecture in a new from scratch application and I feel confused in some points.
I'm trying to make the best choice to not regret it as application will start growing.
Probably my question is a bit stupid, but again i'm new in DDD and trying to make the best choices.
I'm trying to stick to this example https://github.com/ardalis/CleanArchitecture from Ardalis
Here is my model/problem simplified
-ApplicationAggregateRoot
---Application
---Instance
Application has a list of Instance.
Now I have to do an HTTPRequest "/operationA" on the Instance, this can be done by my blazor UI or by my API via controllers.
The result of this HTTP Request "/operationA" will have to be saved in my repository, and do other stuff, so from what I understood here I need an event when I have the HTPP Response something like "OperationAFinishedEvent"
What I don't really know how to figure it out is how should I make this call in my controller/blazor for example.
Should I do (pseudo code):
A)
_repository.GetApplicationById(1).Instances.First(i => i == id).OperationA()
and have some event raised in OperationA() Method of Instance
(something like "OperationASentEvent") which will be wired to a handler that will call _httpClient.OperationA(instance.Url)
Or should I pass by a domain service class for doing the call instead of an event like:
B)
class Controller
{
OperationA(Instance instance)
{
_instanceService.OperationA(instance)
}
}
class InstanceService
{
void OperationA(Instance instance)
{
_httpClient.OperationA(instance.Url);
new OperationAFinishedEvent(instance);
}
}
C) Or call directly
_httpClient.OperationA(instance.Url);
new OperationAFinishedEvent(instance);
from both controller and blazor
Or maybe something else ?
Thank's
It sounds like you have a Blazor client side app as well as a server-side app that you access via an API. So let's address both sides of the app.
In Blazor, you're typically going to minimize application logic and mostly just make calls to the API. So the code required to kick off an operation for an application instance in Blazor should look like this:
var result = await _httpClient.PostAsync(endpointUrl, data);
If that's a long-running process, you might bet back a result that provides you with another endpoint you can query for status. Otherwise the result should just let you know if the process completed successfully or not.
In your API, you will have various endpoints. Normally these endpoints correspond to resources and operations you can take to alter the state of these resources. Your API resources usually correspond to your domain model, but not always 100%. You should generally avoid using HTTP APIs for Remote Procedure Call (RPC) operations, since they're not really designed for that purpose. Instead, think in terms of requests and responses, typically. Imagine you're trying to get your city government to do something, and the way you do that is by filling out a form to hand to a clerk. Then when the action has been completed, they hand you back some more paperwork. The clerk is your API. The papers are your request and response objects. The actual action - the "instance operation" is happening back inside the office where you don't see it as a client, and none of your interactions are with it directly.
So you might have a resource like this:
/Applications/123/Instances/234/PendingOperations
You can list pending operations. You can POST a new operation request. Etc. There might also be a resource for .../CompletedOperations or you might get back an id for your pending operation that you can later use to view its status. The idea is to have an endpoint that represents a noun (a resource) and not a verb (do something).
Hope that helps!
Your domain layer (aggregate root is in there) should only be concerned about their internal state.
The applications layer (where you also use the repository) can call an interface to an other service, using the data from the aggregate root.
The interface is then implemented in a seperate layer.
I would like to implement something that resemble a temporary requests holder in the server side with Asp.Net Core but I have no idea from where should I start. This holder must wait for three distinguished http requests to arrive (by three distinguished clients). Upon receiving those three requests, the server/api will response to each one of those clients with a simple string and everything should be done during the startup time in client side.
From client perspective, it's quite a simple http request/response task with async/await. But from the server/api perspective I still did not figure it out. Any idea? Would socket be helpful here? ...
Note: This communications here are between machine to machine, no human/browser interaction. N(machine/clients)-to-1(machine/server)
If you want to do a very simple implementation. I would suggest a custom implementation:
Create a table on your database (Transactions with columns: ID,
IsStep1Completed, IsStep2Completed, IsStep3Completed)
On each call you can update the table with each step
Everytime check
if all
three calls are completed
Now, this is an oversimplified implementation. You need also to make sure you cover these cases:
What happens if one call fails? you want to drop the whole transaction?
What happens if two calls are completed, but the third is taking a very long time. Do you want to set up a "time to live" transaction?
If a call fails, Do you want to implement a rollback mechanism?
What if the logic of your application needs more/fewer calls as a transaction?
I'm designing a web service and a desktop client application that uses the web service. The interface has a requirement that you need to be able to perform multiple operations and commit them all at once. The operations are basic CRUD operations (create, read, update, delete).
Here's a rough, and Car-ified example of what the workflow would be:
The problem is that the service calls could be spread out over time. I originally had created a REST web service, but REST by definition shouldn't be transactional. The interface has to be able to commit all operations to the database in one go (upon a Save button click).
Edit: An important stipulation is that given the example above, a Car must exist in the database on the server in order to add seats to it. Within a transaction, that car should only be available to the person (session) who is working within that transaction. That limits the ability to send all the operations to the web service at one time at the end of the workflow.
The options I have considered so far are:
1) Implement distributed transactions using SOAP (WCF) and only commit when Save is clicked on the GUI. Is this possible/a good idea for longer transaction lifetimes?
2) Create a unit of work 'service' that takes operations and executes them all within one transaction on the server.
My question is, is 1) possible, or a good/bad idea? Is 2) a good idea, and are there any patterns/tools for implementing this across a web service (REST or SOAP)? Or is there a different way to handle this problem?
I would try this:
POST /unit-of-work
create with response 200
POST /car
create with response 202
POST /seat
create with response 202
etc.
PUT /unit-of-work
set "execute" bit, or somesuch
In this case, car, seat, etc have the unit-of-work specified when they're posted. When the unit-of-work is updated to be "done", all the items are executed.
Another approach would be:
POST /car
create with response 202
POST /seat
create with response 202
etc.
POST /unit-of-work response 200
In this case, car, seat, etc have a bit set saying they're not created yet. The unit-of-work should specify what resources belong to it, and then the back end can flip the bit on the other resources so they're created.
We currently host a lengthy form on our ASP.NET website, which makes use of a public facing facade WCF service to submit information over SSL into our network through a number of other facade services, etc.
We've experienced some issues with downtime on the service chain, and because of this some users have been very frustrated that they complete the lengthy form, only to find out after the fact that the service isn't up. Because of this, we are implementing a type of ping functionality on the form that will ping the service before the form is started, to ensure the service is up.
If the Ping() method is simply called during OnLoad of the form web page, there is potential for DOS attacks through for example a script that continually makes HTTP GET requests against the page.
My question is - From a conceptual level, what is the best way to ensure human interaction with the page while keeping it useable. For example, a CAPTCHA before the Ping() is called and form is started is way too intrusive even though it would be effective at ensuring the form is used properly. On the other hand simply allowing Ping() to fire OnLoad is far too risky for attacks.
One option I've considered is to have a button available to users which allows them to verify service availability and enable the form in one shot. This would at least be a balance between the two. I'm asking for your input on ideas for how best to balance this approach. Any asp.net, c#, or javascript/ajax based answers are fine.
Lastly - I also know there are flaws to this approach of checking service availability as there is no guarantee the service will be available by the time the form is filled out - but the decision has been made to use this approach so please keep your answers on point.
Thanks for the help and input in advance!
UPDATE 1:
In response to Josh's answer below - I should clarify that the form data submitted is sensitive and cannot be cached on the server or stored locally for later submission if the service fails. This is why it is very important to give the user a preemptive heads up. The issues we've had with the services are not intermittent so if the Ping() comes back true, there is an extremely good chance the user will not experience issues submitting the form a few minutes later.
UPDATE 2:
The Ping() Method is currently a server-side c# method, not javascript.
The public facing WCF service is IP-restricted to only allow requests from the public web server
Why don't you just call Ping() when the submit button is pressed and if the service doesn't respond then don't submit the form and show an error.
Something like this in jQuery. This assumses that Ping() returns true if the service is up, false otherwise:
$('#myformid').submit(function() {
var svcUp = Ping();
if(!svcUp)
alert("Sorry, there was an error submitting, please try again.");
return svcUp;
});
Unfortunately any public facing web service that has a low calling cost but high processing cost will be vulnerable to DOS attacks without some type of throttling.
Thankfully WCF has some useful settings for controlling throttling, take a look at MaxConcurrentCalls, MaxConcurrentInstances, and MaxConcurrentSessions
There is really no good solution on the client-side to prevent a DOS attack - I can create a script using your Ping js method that will call it a million times in a loop. You can prevent it on the server side though, by tracking calls per second form the same ip/session/user/otherclient-side identifier. If number of calls per second is over some reasonable limit, you temporarily ban that client.
You can look at http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx - scroll down to "Prevent Denial of Service (DOS) Attack" for an example
Call your function on page load and prior to the submit button. If you have any logging you are using you could insert into a log table for this particular aspx page view and include the IP address of the visitor. Set a threshold and if the IP makes more requests than what you required as proper usage, then put up some type of human-validation item.
Similar but not the same:
How to securely store database connection details
Securely connecting to database within a application
Hi all, I have a C# WinForms application connecting to a database server. The database connection string, including a generic user/pass, is placed in a NHibernate configuration file, which lies in the same directory as the exe file.
Now I have this issue: The user that runs the application should not get to know the username/password of the general database user because I don't want him to rummage around in the database directly.
Alternatively I could hardcode the connection string, which is bad because the administrator must be able to change it if the database is moved or if he wants to switch between dev/test/prod environments.
So long I've found three possibilities:
The first referenced question was generally answered by making the file only readable for the user that runs the application.
But that's not not enough in my case (the user running the application is a person. The database user/pass are general and shouldn't even be accessible by the person.)
The first answer additionally proposed to encrypt the connection data before writing it to the file.
With this approach, the administrator is not able anymore to configure the connection string because he cannot encrypt it by hand.
The second referenced question provides an approach for this very scenario but it seems very complicated.
My questions to you:
This is a very general issue, so isn't there any general "how-to-do-it" way, somehow a "design pattern"?
Is there some support in .NET's config infrastructure?
(optional, maybe out of scope) Can I combine that easily with the NHibernate configuration mechanism?
Update:
In response to the first answers: There are several reasons why I would want to connect to the database directly and not use a web service:
(N)Hibernate can only be used with a database, not webservices (am I right?)
We plan to provide offline capability, i.e. if the database or network should be down, the user can continue his work. To manage this, I'm thinking of having a local, in-proc database, e.g. SQL Server Compact, and using MS Sync framework to synchronize it with the server database as soon as it is up again.
Do you have any further ideas taking this into account?
First of all, letting untrusted users connect to a database is generally not a good idea. So many things can go wrong. Put a web service inbetween.
If you absolutely have to do it, make it so that it doesn't matter even if they get the username and password. Limit their privileges in the database so that they can only execute a few stored procedures that have built-in security checks.
Whatever you do, you can't give the username/password of a privileged user to an untrusted person. It's just asking for trouble. No matter how well you try to hide your credentials within an encrypted string inside a binary file or whatnot, there's always a way to find them out. Of course whether anyone'll actually do it depends on how interesting your data is, but silently hoping that mean people with debuggers will just leave you alone is not a very good security measure.
Actually the WebService approach (mentioned in some other answer) means that you move NHibernate and its logic to the web-service. The WebService then, exposes the db functionality available to the application using the WebService's methods.
There is practically only one user for the database, the one the WebService uses and if you want the application user to have different db privileges you abstract it from the WebService layer
In the end, the WinForms application is only aware of the location of the WebService where it requests data through the WebService's methods and you can apply any required security measure between these two endpoints.
For off-line capability it all boils down to making a secure way to persist your data to local storage and providing a synchronization method via the WebService
I have actually done this using a webservice that communicated with the DB and a WinForm application (.NET Compact Framework) that only talked to the webservice and in case of no cellular network coverage it would serialize the changes to the memory card (the data was not important so for my case obscure/obscene security measures where not taken)
UPDATE with a small example as requested (i do find it strange though to ask for an example on this)
you have set up your domain classes and nhibernate configuration and (for example) your repository stuff in a project of type ASP.NET WebService Application. For the sake of simplicity i'm only going to have a single web-service class Foo (in Foo.asmx.cs) and well as a single Bar domain class
so you get this (actual implementation varies):
namespace FWS
{
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class FooService : WebService
{
private readonly ILog errorLogger = LogManager.GetLogger("ErrorRollingLogFileAppender");
private readonly IDaoFactory daoFactory = new DaoFactory();
private readonly ISession nhSession = HibernateSessionManager.Instance.GetSession();
}
[WebMethod]
public Bar[] GetFavoriteBars(string someParam, int? onceMore){
return daoFactory.GetBarDao().GetFavoriteBars(someParam, onceMore); //returns a Bar[]
}
}
and we abstract the daobehaviour, or just use the nhsession directly, exposed as a webmethod.
Now from the WinForm application all you need to do is Add a WebReference which makes all necessary changes to configuration but also generates all necessary classes (in this example, it will create a Bar class as the web-service exposes it).
namespace WinFormK
{
public class KForm(): System.Windows.Forms.Form
{
public void Do()
{
var service = new FWS.FooService();
string filePath = "C:\\temp\FooData.xml";
Bar[] fetched = service.GetFavoriteBars("yes!", null);
//lets write this to local storage
var frosties = new XmlSerializer(typeof(Bar));
TextReader reader = new StreamReader(filePath);
try
{
var persisted = (T)frosties.Deserialize(reader);
}
catch(InvalidOperationException)
{
//spock, do something
}
finally
{
reader.Close();
reader.Dispose();
}
}
}
}
there are certain things you have to take note to:
You essentially lose lazy stuff, or at least you lose it in your winform application. The XML serializer cannot serialize proxies and as such you either turn of lazy fetching on those collections/properties or you use the [XmlIgnore] attribute which in turn do what it implies on serialization.
You cannot return interfaces on the WebMethod signatures. They have to be concrete classes. So, returning IList<Bar> will have to be transformed to List<Bar> or something of the like
The webservice is executed by IIS and is visible from a web browser. By default, only local browser requests will be served (but that can be changed) so you can test your data access layer separately of what your winform does.
The receiving end (winform app) has no knowledge of NHibernate whatsoever.
In the example above i've kept the same name for the dao-methods for the web-methods; As long as you didn't keep nhibernate--specific methods in your dao's (lets say like a NHibernate.Criterions.Order parameter) you will probably find no problem. In fact you can have as many .asmx classes in your webservice as you want, probably even 'map' them to the corresponding dao's (like public class FooService : WebService, public class BarService : WebService, public class CheService : WebService where each corresponds to a DAO).
You will probably have to write some kind of polling method between your endpoints to keep your presented data fresh.
WebService data is verbose; extremely so. It is advisable to zip them or something before sending them over the wire (and maybe encrypt them as well)
the win application only knows a configuration entry: http://server/FWS/FooService.asmx
Webservices have Session disabled by default. remember that before starting using the session for user data.
You will probably have to write some kind of authentication for the webservice
In the example above i am returning a Bar[] with Bar being mapped with nhibernate. More often than not this may not be the case and you may be required to write an auxiliary class WSBar where it adapts the original Bar class to what the webservice and the winform application can consume. This class is actually just a data carrier. Again this depends on how much integration exists with your domain classes and nhibernate as well as how muxh complicated your classes are: Certain data structures cannot be serialized by default.
This model may not suit what you have already done with your application
I think it's hard to do : it's like you don't want a user of stackoverflow to know his password.
A user can always trace his network traffic and see the user/password (you can had an encoding, but it still won't be 100% sure I think).
I think that you should add a webservice between your user and your database with a unique id for each user.
This is why database desktop apps suck. There is no good way to slice it. Best bet would be to use stored procedures or web services. Basically, another layer that can be locked down and control access to the database.