CustomConverter to compare to a property on the same class in web api - asp.net-core

I've been writing a few customconverters, extending Newtonsofts JsonConverter and stumbled on a little problem. Say I have two properties on a class, but they cannot be the same value. Is it possible to find the value of another property in a converter... for example, say I have a model like so.
I'd want to be able to check the value of Surname in CustomCompareConverter to ensure its not the same value as Firstname
public class Person
{
[JsonConverter(typeof(CustomCompareConverter), "Surname")]
public string Firstname { get; set; }
public string Surname { get; set; }
}
```

You are trying to do multiple things with the json deserialization process that really should be separated
converting some external json into your domain object
validating the domain object.
The fact that the Surname cannot match the FirstName property is a business rule of your domain. So keep that within your domain. You can:
write a separate validator class that will check the state of your
person object and return a list of validation failures
implement IValidatableObject on your Person class and implement the
interface
write a custom validator like in this SO question
Use the JSON deserialization process as an anti-corruption layer to keep the details of external systems out of your your domain structure. Once you've take the extenal object and converted it to your domain object then use conventional means to validate that your domain object.

Related

Should I restrict the construction of a domain object to an external service?

Let's say I have the value object LicensePlate. It is part of a Car, which is an entity in my domain. However, the logic for building the plate doesn't belong to my domain, I simply obtain that from a domain service RegistrationAgency.obtainPlate(Car car), implemented in the infrastrucure layer as DMV.obtainPlate(Car car), which calls an external API.
Now, I feel like I should restrict the construction of the LicensePlate to the service, so I can be sure that any instance of LicensePlate is valid (i.e was made by a registration agency). Is that a justified concern?
Anyway, the solutions I can think of is making LicensePlate's constructor private and adding to the class a static factory method, let's say LicensePlate.build(car, licenseNumberFactory), with LicenseNumberFactory being the one responsible for calling the external API. How messy is that? What about the DDD? Am I respecting it? Should I just make LicensePlate public instead and avoid all of this?
Should I just make LicensePlate public instead and avoid all of this?
Yes
The value object LicensePlate should be able to enforce its own invariants, e.g. cannot be null / must contains numbers and letters / whatever else.
public class LicensePlate
{
public string RegNumber { get; init; }
public LicensePlate(string regNumber)
{
if (string.IsNullOrWhitespace(regNumber))
throw ArgumentOutOfRangeException(nameof(regNumber));
// perform other invariant checks;
RegNumber = regNumber;
}
}
Now you have a license plate that enforces its own invariants (within its sphere of knowledge, at least). Your car entity will look something like:
public class Car
{
public string Model { get; private set; }
public string Color { get; private set; }
public LicensePlate LicensePlate { get; private set; }
public Car(string model, string color, LicensePlate licensePlate)
{
Model = model;
Color = color;
LicensePlate = licensePlate;
}
}
so I can be sure that any instance of LicensePlate is valid (i.e was
made by a registration agency)
If registration agency means that the plate must have been created by a trusted service then that is up to the infrastructure to enforce.
You might think that any caller could have created a license plate to put on your car entity. This is true. But, if that caller does not have access to your infrastructure (database) then creating that entity does not cause any risks as the caller (infrastructure) that may have provided a spoof license plate cannot persist it in your infrastructure (database).
If the same infrastructure codebase that has access to your database is used to make the call to the license plate generation API, then all is good.
If a completely different infrastructure wishes to make use of the Car entity but with license plates created by a different service (or a mock service when testing), then that is up to the infrastructure / application layer. Indeed, this is a feature of DDD layering. The Car entity cannot be expected to enforce invariants that are outside of its control (e.g. whether the value object was acquired from a specific external service).
Anyway, the solutions I can think of is making LicensePlate's
constructor private and adding to the class a static factory method,
let's say LicensePlate.build(car, licenseNumberFactory)
You could do that, but you still don't know if the licenseNumberFactory itself is spoofed by the infrastructure layer.
And you don't want your entity model to have to know about infrastructure implementation.

WCF result deserializing to default values for value types in a list of key/value pairs

I have a WCF service and the result is a custom TimeSeries class defined as:
[DataContract]
public class TimeSeries
{
[DataMember]
public string Name { get; set; }
[DataMember]
public List<KeyValuePair<DateTime, double>> Data { get; set; }
}
My service method creates an array of these objects to return. Debugging the service method, I can see that an array containing one of these objects is created correctly (it has a name and 37 vk pairs of data). Using Fiddler, I can see that the object is being serialized and sent (the data is still correct in the HTTP response). However the problem comes when on the client I check the result object and it is incorrect. Specifically, I get a TimeSeries object with the correct name, and the correct number of of kv pairs, but they contain the default values for each DateTime and double (ie 01/01/0001 12:00AM & 0.0).
My client is Silverlight v4 and I am using an automagically generated service reference. The problem appears to be related to deserialization. Anyone have any thoughts as to why it is doing this, what I am missing, or how I can fix it?
As it is stated in Serializing a list of Key/Value pairs to XML:
KeyValuePair is not serializable, because it has read-only properties
So you need your own class, just like the answer on that page says.
An alternative rather than using your own class is to use a Dictionary<DateTime,double> instead which seems to serialize and deserialize fine.

C# constructor using a dynamic vs Interface as a parameter

In the benefit of creating clean decoupled code in c# I was hoping to get some feedback on using a dynamic parameter to construct objects. Typically I believe you'd create an interface and use the interface as the contract, but then you have to create interfaces for all your classes which I think is kind of icky...
So, my question is what are the pros and cons of doing something like this:
class Class1
{
public string Description { get; set; }
public string Name { get; set; }
public Class1(dynamic obj)
{
Name = obj.Name;
Description = obj.Description;
}
}
vs
class Class1
{
public string Description { get; set; }
public string Name { get; set; }
public Class1(IClass1 obj)
{
Name = obj.Name;
Description = obj.Description;
}
}
Pros of the interface:
The compiler will tell you if you're using the wrong kind of argument
The signature of the constructor tells you what's required from the parameter
Pros of dynamic:
You don't need to declare the interface or implement it
Existing classes with Name and Description properties can be used with no change
Anonymous types can be used within the same assembly if they have Name and Description properties
Personally I typically use C# as a statically typed language unless I'm interacting with something naturally dynamic (e.g. where I'd otherwise use reflection, or calling into COM or the DLR)... but I can see that in some cases this could be useful. Just don't over-do it :)
In both scenarios for the method to function properly as expected the objects being passed into the method must have your Name and Description properties.
My concern is that the best practice for using a dynamic as you have, you would need to provide additional method documentation to ensure other programmers or even yourself six months from now know the expected data contracts that must be present on the object being passed and even then you really should write error handling into your method to ensure it functions as expected when that contract is broken.
Does all these potential gotchas out weight the hypothetical gain of not writing an interface which in the example given would be literally only a 5 basic lines of code, which would then do everything your forcing yourself to do manually.
Assuming you want to follow best practices which lead to well documented and easy to read code. I would lean towards using an interface for this purpose.

Change datamember name based on method

[DataContract()]
public class Contract
{
.........
Some Properties with DataMembers Attribute.
............
..............
[DataMember(Name = "FirstName")]
public string Name { get; set; }
}
I have above class and I have two web methods (operations)
In 1st web method I want to expose Name as FirstName and in 2nd web method expose Name as LastName.
I don't want to create separate data contracts.
Please tell me how to achieve this?
You can use reflection and change the value of the attribute at runtime depending on which method you in currently. Check out these links on StackOverflow:
How to set attributes values using reflection
Change Attribute's parameter at runtime
But I think the best way would be to either have 2 separate contracts or create a contract with both properties.
You can also implement a surrogate to special-case this type during serialization. As an example, see the Data Contract Surrogate sample.

Can you change from a base class to a joined subclass type in nhibernate?

I have document scanning system where several types of documents are scanned. Initially, the document has no information when its scanned, then they get classified and additional information is entered for them in a second step later. So, I have a base class called Document, and subclasses for each type with their respective metadata like below. I have it setup as a table-per-subclass (joined subclass) mapping in NHibernate.
public class Document
{
public int ID { get; set; }
public string FilePath { get; set; }
}
public class Certificate : Document
{
// certificate-specific fields
}
public class Correspondence : Document
{
// correspondence-specific fields
}
What I need to be able to do is create a Document class first and save it. Then retrieve in a second step later on and convert it to one of the subclass types and fill in the rest of its information. What would be the best approach to do this, and is this even possible with NHibernate? If at all possible I would like to retain the original document record, but its not a dealbreaker if I have to jettison it.
Unfortunately, NHibernate does not allow you to switch between subclasses after initial creation; to get this working the way you want, you have 3 options:
Use a native sql call to change the discriminator (and possibly) add or change any subclass-related fields.
Copy the contents of your object to a new object of the proper class and then delete the original.
Don't use subclasses, control the state of your object through an enumeration or some other mechanism that allows you to determine their type at run-time.
This issue has already been discussed here. I would go with Terry Wilcox's tip to use a role for this. Composition over inheritance.