Generic comparison logic for objects - c#

I am working on the back end of a REST API -
For a POST request (in one of the scenarios) I need to validate if the object sent by the user is the same as the one stored in the Db.
What is an efficient way of comparing two objects in C#?
PS - I want the comparison logic to withstand the test of time, i.e. being a huge team I do not rely on people adding new fields in the IComparable logic. Anyone can add a new property to the object and that would skip the validation test if they do not add that to the comparison logic.
I am thinking of Deserializing the object stored in our database and compare it to the deserialized version of that the user POSTS.
Any thoughts?

Automagically implement IComparable<T> on T for ValueObjects (objects for which their identity is all of their fields) is a form of Aspect-Oriented Programming (AOP).
There are various Aspect frameworks for C#.
In this case I would advise you use PM> Install-Package Equals.Fody.
To use it is pretty easy.
[Equals]
public class Foo
{
public int X { get; set; }
public int Y { get; set; }
}

Related

How can I map JSON body properties as dynamic parameters of a .NET Core web API action method with validation?

I have to build a .NET Core REST API and I have about two dozen endpoints that take in simple JSON objects like:-
{
"foo": 23,
"bar": "bar_value"
}
and
{
"foo": 12,
"baz": true
}
etc.
Some properties, such as foo above, are common among several endpoints but have different validation requirements. In some endpoints they are required, in others, they are not and so on. I can't change these JSON payloads as they're generated by a third party I don't have any control over.
How can I map these parameters to endpoints in a .NET Core API method directly, without a class?
I can, of course, create a class for each endpoint, such as
public class SomeObject
{
[Required]
[Range(0, 100)]
public int? Foo { get; set; }
public string bar { get; set; }
}
public class SomeOtherObject
{
public int? Foo { get; set; }
[Required]
public bool Baz { get; set; }
}
...
Note the different validation rules.
But I don't feel like creating some two dozen classes. I'd much rather just specify them directly in the endpoint method:
[HttpPut]
[Route("/some-route")]
public IActionResult SomeAction([Required, Range(0, 100)] int? foo, byte? bar)
{
...
}
[HttpPut]
[Route("/some-other-route")]
public IActionResult SomeOtherAction(int? foo, [Required] baz)
{
...
}
It would be much easier to read and figure out which property is required and when by just looking at the methods instead of opening one of two dozen similarly named class files or opening one single file with two dozen similarly named classes with properties of the same name.
So how can I get .NET Core to parse the JSON and assign the property values to the action method parameters?
I'm not aware of a direct answer to this question as specified, so I'll answer this with an alternative approach as an XY problem based on your statement "It would be much easier to read and figure out which property is required and when by just looking at the methods".
This assumes there's not an easy way document your own API surface area if you're using classes. In your example, you're already writing a large amount of logic in the method signature itself, not to mention potential behaviors for default values, etc., that can make those signatures progressively harder to read and understand, and that's exactly what input model classes and model validation are designed to help encapsulate. Furthermore, now that you've decomposed the model into its parts, it becomes increasingly complex to handle validation issues as a cohesive model, regardless of whether it could be done. By accepting the entire object at once, you can run a ModelState.IsValid check, aggregate errors, or add your own and quickly return that from the controller.
By adding XML documentation to your endpoint methods and input model classes, you also open up the easy path of adding a Swagger page with Swashbuckle, which will provide a simple way for you to inspect what the model value types are and which ones are required, etc., as well as example JSON bodies in the Swagger page itself with full documentation as to the purpose of all the parameters.
While you do end up with a bunch of model classes, it's just a button press away from Visual Studio to hop to your class and see your validation requirements and input types while "in code". If class generation is frustrating, you can quickly drop your JSON samples into a class generator online and get a "pretty good" starting point for the input models: https://json2csharp.com/

Distinct event types on same collection - MongoDB and .NET Core

I want to use MongoDB to store domain events in a system written with .NET Core and C#.
I've googled a little about this, and it seems it is a common practice to have a single collection called events and simply store all events there. I've also seem people to create one field type to distinguish events. An example of this is Slide 66 of this presentation.
So if I wanted to save one UserCreated event I would add it with type user-created, and so forth.
Now I'm in doubt with respect to the mapping when it comes to using .NET Core.
Two distinct events will in general have different schema, so I think that the automatic mapping would do no good. Of course I could use the option of ignoring extra elements. But it may be the case that two events have subsets of properties which are equal, for example, all of them will have a OccurredOn DateTime. I think this could be an issue.
My idea was to query the field type. Something like:
colection.Find(BsonDocument.Parse("{type: user-created}"))
But I don't know if that is the best option, or if there is a way to set up a mapping so that the MongoDrive knows that whenever we try to get an instance of UserCreated it should look just for that type, and when we try to insert, it should create the correct type field.
In that case: given that we save distinct event types to the same collection, what is the correct approach to map this into the right C# event objects?
You could use a container like this one.
public class DomainEventContainer
{
public ObjectId Id { get; set; }
public string Type { get; set; }
public string EventData { get; set; }
}
And then based on the value of DomainEventContainer.Type, you could deserialize EventData into your desired type.

.Net Core Binding to a Specific Model given a Specific QueryString Value

I'm in the middle of refactoring an analytics api which needs to allow clients to send events as HTTP GET requests, with their "Hit" data encoded in the URL's QueryString Parameters.
My API's job is to recieve these events, and then place the "valid" events onto a queue in another part of the system for processing.
Some Hits have the same shape. The only thing that makes them different is the value of the type parameter, which all events must have at a minimum.
The problem I've encountered is that based on the Hit type, I'd like to be able to assume the type of each field given to me, which requires model binding. Of course. Currently, I can only find out what model to validate against after checking the value of type - which risks making the API excessively "stringly typed"
An example route would be:
GET https://my.anonymousanalytics.net/capture?type=startAction&amount=300&so_rep=true
Therefore, my Hit would be:
{
type: "startAction",
amount: 300,
so_rep: true
}
Which, hypothetically, could be bound to the Model StackOverflowStartHitModel
class StackOverflowStartHitModel {
public string type { get; } // Q: Could I force the value of this to be "startAction"?
? public int amount { get; }
public boolean so_rep { get; }
}
Why am I asking this here? Well I'm normally a JavaScript developer, but everyone who I'd normally turn to for C# wisdom is off work with the flu.
I have experimented with the [FromQuery] attribute decorator, but my concern is that for Hits that are the exact same shape, I might not be able to tell the difference between whether it is a startAction or an endAction, for example.
you're going to need to have a validation engine of some sort, but do not confuse this with your UI model validation. It sounds like you really have one model with a number of valid states which really is business logic.
Your model looks like this:
public class StackOverflowModel
{
public string type { get; set;}
public int amount { get; set; }
public bool so_rep { get; set;}
}
it doesn't matter what value your type field has and you don't need to hard-code it either, it will be captured as is and then it can be checked against valid states.
There are a number of ways to do this, that I can think of.
One option would be to create a list of valid rules ( states ) and then simply check if your input model matches any of them. One way to implement something like this could be with a library like FluentValidation. You can see an example here: Validation Rules and Business Rules in MVC
Another option would be to use some sort of Pattern Matching techniques like described here: https://learn.microsoft.com/en-us/dotnet/csharp/pattern-matching
Whichever option you go with, make sure you put this validation stuff in a separate class, maybe even a separate project. You can then add tests for each rule that you have to make sure everything works. This will also keep your controller light.
You haven't given examples of valid and invalid states, but I am guessing you're really talking about variations of those 3 parameters such as, when type is "something" then amount can only be < 200 and so_rep can only be "whatever". This can be done quite nicely with the FluentValidation library.

Building Generic Apps - Allowing Customer-specific Options

I've built an open source application, and I'd be curious to know how others are handling customer-specific requests. It's important to me to keep the app simple; I'm not trying to make it all things for all people. Apps can get bloated, complex, and just about unusable that way. However, there are some customer-specific options that would be nice (it just wouldn't apply to all customers). For example...
Say we have a domain entity called Server. In the UI, we let a customer pick from a list of servers. For one company, it's helpful to filter the servers by location (US, Germany, France, etc...). It would be easy enough to add a server property like this:
public class Server
{
public Location Location { get; set; }
// other properties here
}
My concern is that Server could become bloated with properties over time. And even if I only add location, not all customers would care about that property.
One option is to allow for user-defined fields:
public class Server
{
public string UserField1 { get; set; }
public string UserField2 { get; set; }
public string UserField3 { get; set; }
// etc...
// other properties here
}
Is that the best way to handle this? I don't like the fact that type safety is gone by making everything a string. Are there other/better ways that people are handling issues like this? Is there even a design pattern for something like this?
In my opinion, a good design pattern for something like this is to use schemas at the database level and then basic inheritance at the class level.
CREATE TABLE dbo.A (
ColumnA INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
ColumnB VARCHAR(50),
ColumnC INT,
etc.
)
And now we have a client who needs some specific functionality, so let's create an extension to this table in a different schema:
CREATE TABLE CustomerA.A (
ColumnA INT NOT NULL PRIMARY KEY,
Location VARCHAR(50)
)
But now we have another client who needs to extend it differently:
CREATE TABLE CustomerB.B (
ColumnA INT NOT NULL PRIMARY KEY,
DataCenterID INT
)
Though the fields may not be relevant, you get the idea, and so now we need to build the customer specific domain models here:
public abstract class A
{
public int ColumnA { get; set; }
public string ColumnB { get; set; }
public int ColumnC { get; set; }
}
public class CustomerA_A : A
{
public string Location { get; set; }
}
public class CustomerB_A : A
{
public int DataCenterID { get; set; }
}
And so now when we need to build something for Customer A, we'll build their subclass, and for Customer B theirs, and so on.
Now, FYI, this is the beginnings of a very dynamic system. I say that because the piece that's missing, that's not yet dynamic, is the user-interface. There is a significant number of ways that can be accomplished, but way outside the scope of this question. That is something you'll have to consider. I say that because the way you manage the interface will determine how you even know to build which subclass.
I hope this has helped.
The usual approach early on is to use the config XML files for this sort of thing. But programming for client-specific needs requires a whole mindset around how you program. Refer to this answer to a similar question.
Of course it always depends on how much customization you want to allow. In our product we went as far as enabling users to completely defined their own entities with properties and relations among them. Basically, every EntityObject, as we call our entities, in the end consists of a value collection and a reference to a meta-model describing the values within them. We designed our own query language that allows us to query the database and use expressions that are translate-able to any target language (although we currently only do SQL and .net).
The game does not end there and you quickly find that things like validation rules, permissions, default values and so on become a must have. Of course all of this then requires UI support, at least for the execution of the meta-model.
So it really depends on the amount of adjustment a end-user should be able to perform. I'd guess that in most cases simple user fields, as you described, will be sufficient. In that case I would provide a single field and store JSON text within that. In the UI you can then provide at least a semi-decent UI allowing structure and extensibility.
Option 1: Say "no". :-)
And while I say that (half) jokingly, there is some truth to it. Too often, developers open themselves up to endless customization by allowing one or two custom features, setting the snowball in motion.
Of course, this has to be balanced, and it sounds like you may be doing this to an extent. But if you truly want to keep your app simple, then keep it simple and avoid adding customizations like this.
Option 2: Inheritance.
If you really need to add the customization, I would lean the way of building a base class with all "standard" options, and then building customer-specific classes containing customer-specific optimizations.
For example:
public class Server
{
// all standard properties here
}
Then for Joe's Pizza, you can have:
public class JoesPizzaServer : Server
{
public Location Location { get; set; }
}
The side-benefit to this is that it will allow you to base your presentation views off of the client-specific (or base) models.
For example, in MVC you could set up your view models like this, and then you could have specific views for each customer.
For example, Bob's Burgers would have its own view on the base model:
#model MyApp.Server
#* implement the base form *#
And Joe's Pizza's view would use the custom model:
#model MyApp.JoesPizza
#* implement the base form -- a partial view -- with addtional custom fields
MVC does a really good job of supporting this type of pattern. If you're not using MVC (maybe WPF or Web Forms), there are still ways to leverage partial "view" files for accomplishing something similar.
Of course, your database can (and probably should) support a similar inheritance model. Entity Framework even supports various inheritance models like this.
I may be wrong here, but it looks like you want to handle different versions of your software with the same code base. I can think of two approaches for this:
Actually define different versions for it and handle changes for each client. This won't give you problems from the domain-modeling point of view, but will require a supporting infrastructure, which will have to scale according to your client requirements. There are some related questions out there (e.g. this, this and this).
Handle this at the domain-model level, as a user-defined configuration. The advantage of this approach is that you don't have to incorporate multiple versions of your software, but this comes at the expense of making your model more generic and potentially more complex. Also your tests will surely have to be adapted to handle different scenarios. If you are going in that direction I would model an object representing the attribute (with a name and a value) and consider the Server class as having a collection of attributes. In that way your model still captures your requirements in an OO style.
HTH
I approach from Python that I think would work rather well hear is a dictionary. The key is your field name, the value is the, errrrr... value ;)
It'd be simple enough to represent in a database too.

Validation Framework in .NET that can do edits between fields

From my experience many validation frameworks in .NET allow you to validate a single field at a time for doing things like ensuring a field is a postal code or email address for instance. I usually call these within-field edits.
In my project we often have to do between-field-edits though. For instance, if you have a class like this:
public class Range
{
public int Min { get; set; }
public int Max { get; set; }
}
you might want to ensure that Max is greater than Min. You might also want to do some validation against an external object. For instance given you have a class like this:
public class Person
{
public string PostalCode { get; set; }
}
and for whatever reason you want to ensure that Postal Code exists in a database or a file provided to you. I have more complex examples like where a user provides a data dictionary and you want to validate your object against that data dictionary.
My question is: can we use any of the existing validation frameworks (TNValidate, NHibernate Validator) for .NET or do we need to use a rules engine or what?? How do you people in the real world deal with this situation? :-)
There's only one validation framework that I know well and that is Enterprise Library Validation Application Block, or VAB for short. I will answer your questions from the context of the VAB.
First question: Can you do state (between-field) validation in VAB?
Yes you can. There are multiple ways to do this. You can choose for the self validation mechanism, as follows:
[HasSelfValidation]
public class Range
{
public int Min { get; set; }
public int Max { get; set; }
[SelfValidation]
public void ValidateRange(ValidationResults results)
{
if (this.Max < this.Min)
{
results.AddResult(
new ValidationResult("Max less than min", this, "", "", null));
}
}
}
I must say I personally don't like this type of validations, especially when validating my domain entities, because I like to keep my validations separate from the validation logic (and keep my domain logic free from references to any validation framework). However, they need considerably less code than the alternative, which is writing a custom validator class. Here's an example:
[ConfigurationElementType(typeof(CustomValidatorData))]
public sealed class RangeValidator : Validator
{
public RangeValidator(NameValueCollection attributes)
: base(string.Empty, string.Empty) { }
protected override string DefaultMessageTemplate
{
get { throw new NotImplementedException(); }
}
protected override void DoValidate(object objectToValidate,
object currentTarget, string key, ValidationResults results)
{
Range range = (Range)currentTarget;
if (range.Max < range.Min)
{
this.LogValidationResult(results,
"Max less than min", currentTarget, key);
}
}
}
After writing this class you can hook this class up in your validation configuration file like this:
<validation>
<type name="Range" defaultRuleset="Default" assemblyName="[Range Assembly]">
<ruleset name="Default">
<validator type="[Namespace].RangeValidator, [Validator Assembly]"
name="Range Validator" />
</ruleset>
</type>
</validation>
Second question: How to do complex validations with possible interaction a database (with VAB).
The examples I give for the first question are also usable for this. You can use the same techniques: self validation and custom validator. Your scenario where you want to check a value in a database is actually a simple one, because the validity of your object is not based on its context. You can simply check the state of the object against the database. It gets more complicated when the context in which an object lives gets important (but it is possible with VAB). Imagine for instance that you want to write a validation that ensures that every customer, at a given moment in time, has no more than two unshipped orders. This not only means that you have to check the database, but perhaps new orders that are added or orders are deleted within that same context. This problem is not VAB specific, you will have the same problems with every framework you choose. I've written an article that describes the complexities we're facing with in these situations (read and shiver).
Third question: How do you people in the real world deal with this situation?
I do these types of validation with the VAB in production code. It works great, but VAB is not very easy to learn. Still, I love what we can do with VAB, and it will only get better when v5.0 comes out. When you want to learn it, start with reading the ValidationHOL.pdf document that you can found in the Hands-On Labs download.
I hope this helps.
I build custom validation controls when I need anything that's not included out of the box. The nice thing here is that these custom validators are re-usable and they can act on multiple fields. Here's an example I posted to CodeProject of an AtLeastOneOf validator that lets you require that at least one field in a group has a value:
http://www.codeproject.com/KB/validation/AtLeastOneOfValidator.aspx
The code included in the download should work as an easy to follow sample of how you could go about it. The downside here is that Validation controls included with ASP.Net don't often work well with asp.net-ajax.

Categories