Decoupling pdf rendering into a reusable assembly / using different rendering strategies - c#

We have two apps: desktop client & mvc backend. Both apps have printing functionality. And it's quite obvious that we're repeating ourselves with that. Let me explain this. The routine looks as follows:
User enters his ID / sends his data to the mvc endpoint;
We check the db if all necessary data is valid;
We compose a viewmodel (mvc) / dto (desktop) object;
As a requirement there are two type of documents to be printed;
Then we make identical calls to a PDF-rendering API (we use PdfSharp) composing two documents.
I think it would be better if we had that pdf-composing logics in a separate assembly. Then it could be reusable. The problem with this is that documents use slightly different properties (data). As a solution we can use one shared dto with all necessary properties:
public IEnumerable<string> Render(DocumentDto document) {
// ioc
foreach(var strategy in this.strategies) {
if(strategy.CanRender(document)) {
yield strategy.Render(document);
}
}
}
We can also inject DbContext object into our startegies. And each strategy would request the desired properties on its own:
public class StrategyA {
// I'll omit ctor here
private DbContext db;
public string Render() {
// make db calls
// render the document
}
}
But I don't think this is a good solution either since it requires a db dependency.
Can we design it so that each strategy only uses its own set of properties?

Related

DDD construct AggregateRoot Entity from external API, Repositories and Domain Services

Trying to apply DDD principles to small project... I have PlayerProfile aggregate root, which consists of Club entity and collection of Rating value objects. Periodically I have to sync all PlayerProfile's entities from external portal, parsing the raw HTML.
For now I come up with the solution to wrap the code, which renew the PlayerProfile's in simple PlayerProfileRepository, something like this:
public interface IPlayerProfileRepository
{
Task<IReadOnlyCollection<PlayerProfile>> SyncPlayersProfilesFromPortal(string sourceUrl);
// other methods, which works with data storage
}
First, I don't really like the idea of mixing method, which work with data storage with the methods, which work with external resource (HTML pages) to periodically create PlayerProfile. For me it sounds more like PlayerProfileFactory responsibilities?
The actual implementation of IPlayerProfileRepository delegates parsing of actual pages to 3 IPageParser's, which actually lives in the same layer as my repositories do. Something like this:
public PlayerProfileRepository(
IPageParser<ParseClubDto> clubPageParser,
IPageParser<ParsePlayerProfileDto> playerProfilePageParser,
IPageParser<ParseRatingDto> ratingPageParser)
{
_playerProfilePageParser = playerProfilePageParser;
_clubPageParser = clubPageParser;
}
I am not quite sure if all these Dtos are in fact Dtos as soon as they are used only from IPageParser's to save intermediate data while parsing the pages. I would like to keep them closely to IPageParser implementations in data service layer, but not to share them in separate Dtos project and maybe named differently.
After ParseClubDto, ParsePlayerProfileDto and ParseRatingDto parsed, I passed it to PlayerProfileFactory.Create factory method, something like this:
var playerProfiles = new List<PlayerProfile>();
var clubs = await _clubPageParser.ParseAsync(sourceUrl);
foreach (var club in clubs)
{
var clubPlayers = await _playerProfilePageParser.ParseAsync(club.PlayersPageUrl);
foreach (var clubPlayer in clubPlayers)
{
var ratings = await _ratingPageParser.ParseAsync(clubPlayer.RatingsPageUrl);
playerProfiles.Add(PlayerProfileFactory.Create(club, clubPlayer, ratings));
}
}
return playerProfiles;
After this is done I have to perform actual syncing with existing agreggate roots in DB, which I do simple by calling ResyncFrom(PlayerProfile profile) on aggregate root or should it be more like separate PlayerProfile domain service?
In general I got a feeling that I am doing something wrong, so please any comments are welcomed?
I think that your example is a case of integration between two BCs using the anti corruption layer pattern.
I would have a port (interface in the domain) with a method contract that returns a list of player profile aggregates.
In the infrastructure layer I would have an adapter that implements the port by reading the html data from the remote portal (for example using a REST API ) and constructing the aggregates from that data.
In the application layer I would have an application service in which you inject both the port and the player profile aggregate repository that deals with the local db. The application service calls the port to construct the aggregates, and then calls the repository to store them.
I would run this application service periodically.
This would be an async integration without events, but you could implement it with events if the remote portal fires events.
IPlayerProfileRepository interface is usually defined in the Domain and describes to the outside world how the Aggregate Root should be retrieved, usually by the Id. So the method SyncPlayersProfilesFromPortal should certainly not be a part of this interface.
Syncing data is an infrastructure concern and can be done asynchronously in the background as already suggested in the previous answer.

Shared data and shared methods in .NET Core Razor

I am new to C# and .NET and am about to create a little CRUD project based on .NET Core 2.1, EF 2.1 and Razor pages.
I have this very basic question:
I need some basic methods and some basic data in many of my cshtml.cs controllers and I want to create one central place to define them. Which is the recommended way to do that?
I envision one or more static classes with static properties to provide common data for the controllers, and with methods that can be used by all controllers. But is this the recommended solution? And in which folder of the project should I place them? Any naming conventions would be appreciated too.
An example for central data I want to store is a dictionary of database errors like this:
Dictionary<int, string> _sqlErrorTextDict = new Dictionary<int, string>
{
{547,
"This operation failed because another data entry uses this entry."},
{2601,
"One of the properties is marked as Unique index and there is already an entry with that value."}
};
An example for a central method would be code that receives a DB error exception object and creates a list of error text messages from it, ready to be displayed in any view.
You can use singletons for this. Here is a simple implementation based on your example:
First, create a class for storing the values. Your class could have any definition you find fit for your values. I am using this structure to stay closest to your code:
class CommonData : Dictionary<int, string>
{
}
In your startup.cs class you could use this:
services.AddSingleton(new CommonData {
{547,
"This operation failed because another data entry uses this entry."},
{2601,
"One of the properties is marked as Unique index and there is already an entry with that value."}
});
If you have too much data and would like to reduce the code on this file, you an create an extension function for this.
Within your controllers (and other services), you can use dependency injection to access this data:
private readonly CommonData commonData;
public HomeController(CommonData commonData)
{
this.commonData = commonData;
}

Passing a Data Object Between Dependent Factories

I'm currently using an IoC container, unity, for my program.
I have multiple chained factories. One calling the next to create an object it needs for populating a property. All the factories use the same raw data object in order to build their respective objects. The raw data object describes how to create all the various objects. Currently each factory has a Create method that takes in a couple parameters to state what location the object represents.
My problem is how/where do I pass in the raw data object to each factory in order for them to do their jobs?
Injecting the object into the Create() methods seems to be more procedural than object oriented. However if I inject the object into each factory's constructor then how would I resolve each factory correctly. Not to mention that these factories need to be able to work on different raw data objects. Maybe there is a better architecture over all?
Below represents the type of structure I have, minus passing the raw object anywhere.
class PhysicalObjectFactory
{
private readonly StructureAFactory _structureAFactory;
private readonly Parser _parser;
public PhysicalObjectFactory(StructureAFactory structureAFactory, Parser _parser)
{
_structureAFactory = structureAFactory;
this._parser = _parser;
}
public PhysicalObject CreatePhysicalObject()
{
RawDataObject rawDataObject = _parser.GetFromFile("foo.txt");
// do stuff
PhysicalObject physicalObject = new PhysicalObject();
physicalObject.StructureA = _structureAFactory.Create(num1, num2);
// do more stuff
return physicalObject;
}
}
class StructureAFactory
{
private readonly StructureBFactory _structureBFactory;
public StructureAFactory(StructureBFactory structureBFactory)
{
_structureBFactory = structureBFactory;
}
public StructureA Create(int a, int b)
{
// do stuff
StructureA structureA = new StructureA();
structureA.StructureB = _structureBFactory.Create(num76, num33);
// do more stuff
return structureA;
}
}
class StructureBFactory
{
public StructureBFactory(){}
public StructureB Create(int a, int b)
{
StructureB structureB = new StructureB();
// do stuff
return structureB;
}
}
My problem is how/where do I pass in the raw data object to each
factory in order for them to do their jobs?
In general you should pass in runtime data through methods and compile-time/design-time/configuration data through constructor injection.
Your services are composed at a different moment in time as when they are used. Those services can live for a long time and this means they can be used many times with different runtime values. If you make this distinction between runtime data and data that doesn't change throughout the lifetime of the service, your options become much clearer.
So the question is whether this raw data you're passing in is changing on each call or if its fixed. Perhaps it is partially fixed. In that case you should separate the the data; only pass the runtime data on through the Create methods. It seems obvious that since the factories are chained, the data they need to create that part of the object is passed on to them through their Create method.
Sometimes however, you've got some data that's in between. It is data that will change during the lifetime of the application, but do don't want to pass it on through method calls, because it's not up to the caller to determine what those values are. This is contextual information. A clear example of this is information about the logged in user that is executing the request. You don't want the caller (for instance your presentation layer) to pass that information on, since this is extra work, and a potential security risk if the presentation layer forgets to pass this information on, or accidentally passes on some invalid value.
In that case the most common solution is to inject a service that provides consumers with this information. In the case of the user information you would inject an IUserContext service that contains a UserName or UserId property, perhaps a IsInRole(string) method or something similar. The trick here is that not the user information is injected into a consumer, but a service that allows access to this information. In other words, the retrieval of the user information is deferred. This allows the composed object graph to stay independent of those contextual information. This makes it easier to compose and validate object graph.

DDD. Method on entity or service?

I'm trying to use DDD when developing a new system. In this system I have places and I need to give access to places based on which adgroups you're a member of. I also need to get a list of allowed places from a list of adgroups.
I've come up with the following:
interface IPlaceRepository
{
Places[] GetPlacesForGroups(AdGroup[] adGroups);
}
class AdGroup()
{
string Name { get; private set; }
}
class Place
{
string Name { get; private set; }
}
Now I need to add a function that grants a group access to a particular place. According to DDD which is the right way to do it? I have a two suggestions.
I assume that adgroups can be considered as value objects.
Add a function to Place.
void GiveAccessTo(AdGroup adGroup) { ... }
and add a function to IPlaceRepository.
void AddGroupToPlace(Place p, Group g) { ... }
Then I need to inject the IPlaceRepository into Place for use inside GiveAccessTo.
Another way maybe is to create an ISecurityService? I can think of a method like this on that service.
void GiveAccessToPlace(AdGroup g, Place p)
In the same way as option 1 I need to implement a method on IPlaceRepository and inject the repository into the service.
Which is the DDD way to do this?
Repositories persist complete aggregates, normally you wouldn't have an AddGroupToPlace method.
Since ADGroup is a value object, you can use the GiveAccessTo method to add the groups to the Place aggregate. After doing that, you use the repository to persist the complete Place aggregate.
Services are mostly used when an operation spans multiple aggregates. This can often be avoided using events though.
(indirect answer)
Not sure if DDD has some rules specifically for your case. I would follow these steps:
Draw on a paper pad the aggregates, paying attention to the root aggregate (which entity contains another one)
Draw your queries
List several approaches to store the list of allowed items
Keep in mind how you would store this, in a document-oriented database or else where (this is where materialized view may complicate things)
Several approaches can be valid, return to your queries and pick the best approach (memory consumption, speed, least number of items required to be queried)
Separate security from business API, use Authorization pattern from the framework you use
Only use white-listing (list all allowed resources, deny all by default)

In domain-driven design, would it be a violation of DDD to put calls to other objects' repostiories in a domain object?

I'm currently refactoring some code on a project that is wrapping up, and I ended up putting a lot of business logic into service classes rather than in the domain objects. At this point most of the domain objects are data containers only. I had decided to write most of the business logic in service objects, and refactor everything afterwards into better, more reuseable, and more readable shapes. That way I could decide what code should be placed into domain objects, and which code should be spun off into new objects of their own, and what code should be left in a service class. So I have some code:
public decimal CaculateBatchTotal(VendorApplicationBatch batch)
{
IList<VendorApplication> applications = AppRepo.GetByBatchId(batch.Id);
if (applications == null || applications.Count == 0)
throw new ArgumentException("There were no applications for this batch, that shouldn't be possible");
decimal total = 0m;
foreach (VendorApplication app in applications)
total += app.Amount;
return total;
}
This code seems like it would make a good addition to a domain object, because it's only input parameter is the domain object itself. Seems like a perfect candidate for some refactoring. But the only problem is that this object calls another object's repository. Which makes me want to leave it in the service class.
My questions are thus:
Where would you put this code?
Would you break this function up?
Where would someone who's following strict Domain-Driven design put it?
Why?
Thanks for your time.
Edit Note: Can't use an ORM on this one, so I can't use a lazy loading solution.
Edit Note2: I can't alter the constructor to take in parameters, because of how the would-be data layer instantiates the domain objects using reflection (not my idea).
Edit Note3: I don't believe that a batch object should be able to total just any list of applications, it seems like it should only be able to total applications that are in that particular batch. Otherwise, it makes more sense to me to leave the function in the service class.
You shouldn't even have access to the repositories from the domain object.
What you can do is either let the service give the domain object the appropriate info or have a delegate in the domain object which is set by a service or in the constructor.
public DomainObject(delegate getApplicationsByBatchID)
{
...
}
I'm no expert on DDD but I remember an article from the great Jeremy Miller that answered this very question for me. You would typically want logic related to your domain objects - inside those objects, but your service class would exec the methods that contain this logic. This helped me push domain specific logic into the entity classes, and keep my service classes less bulky (as I found myself putting to much logic inside the service classes like you mentioned)
Edit: Example
I use the enterprise library for simple validation, so in the entity class I will set an attribute like so:
[StringLengthValidator(1, 100)]
public string Username {
get { return mUsername; }
set { mUsername = value; }
}
The entity inherits from a base class that has the following "IsValid" method that will ensure each object meets the validation criteria
public bool IsValid()
{
mResults = new ValidationResults();
Validate(mResults);
return mResults.IsValid();
}
[SelfValidation()]
public virtual void Validate(ValidationResults results)
{
if (!object.ReferenceEquals(this.GetType(), typeof(BusinessBase<T>))) {
Validator validator = ValidationFactory.CreateValidator(this.GetType());
results.AddAllResults(validator.Validate(this));
}
//before we return the bool value, if we have any validation results map them into the
//broken rules property so the parent class can display them to the end user
if (!results.IsValid()) {
mBrokenRules = new List<BrokenRule>();
foreach (Microsoft.Practices.EnterpriseLibrary.Validation.ValidationResult result in results) {
mRule = new BrokenRule();
mRule.Message = result.Message;
mRule.PropertyName = result.Key.ToString();
mBrokenRules.Add(mRule);
}
}
}
Next we need to execute this "IsValid" method in the service class save method, like so:
public void SaveUser(User UserObject)
{
if (UserObject.IsValid()) {
mRepository.SaveUser(UserObject);
}
}
A more complex example might be a bank account. The deposit logic will live inside the account object, but the service class will call this method.
Why not pass in an IList<VendorApplication> as the parameter instead of a VendorApplicationBatch? The calling code for this presumably would come from a service which would have access to the AppRepo. That way your repository access will be up where it belongs while your domain function can remain blissfully ignorant of where that data came from.
As I understand it (not enough info to know if this is the right design) VendorApplicationBatch should contain a lazy loaded IList inside the domain object, and the logic should stay in the domain.
For Example (air code):
public class VendorApplicationBatch {
private IList<VendorApplication> Applications {get; set;};
public decimal CaculateBatchTotal()
{
if (Applications == null || Applications.Count == 0)
throw new ArgumentException("There were no applications for this batch, that shouldn't be possible");
decimal Total = 0m;
foreach (VendorApplication App in Applications)
Total += App.Amount;
return Total;
}
}
This is easily done with an ORM like NHibernate and I think it would be the best solution.
It seems to me that your CalculateTotal is a service for collections of VendorApplication's, and that returning the collection of VendorApplication's for a Batch fits naturally as a property of the Batch class. So some other service/controller/whatever would retrieve the appropriate collection of VendorApplication's from a batch and pass them to the VendorApplicationTotalCalculator service (or something similar). But that may break some DDD aggregate root service rules or some such thing I'm ignorant of (DDD novice).

Categories