.NET Core: Trim all blank spaces globally using AutoMapper - c#

I have a request for not saving any blank spaces at the beginning and the end. I mean, I should trim every string received in the application until I save it.
I saw that there's a question that almost fits my request, which looks this way based on this question:
Mapper.CreateMap<string, string>()
.ConvertUsing(str => str == null ? null : str.Trim()).Trim());
However, since I'm using .NET Core, AutoMapper.Mapper static object doesn't contain a definition of CreateMap<>, so I guess it might be different on this newer technology.
I tried to define something like this on my Startup.cs, but it didn't work:
services.AddAutoMapper(
cfg => cfg.CreateMap<string, string>().ConvertUsing(str => str == null ? null : str.Trim()),
typeof(Startup)
));
I also saw something like creating custom profile class, like StringTrimmerProfile.cs, and then include that profile on the Startup, but it sounds pretty much the same to what I did before. That proposal was taken from here.
I don't want to perform this action on every profile, I want to do it globally for every string being mapped on the application.
How can I define a global pre-mapping to be applied on every model?
Sounds easy, but I couldn't find the answer since all the info seems to be for .NET 4.5 or lower.
EDIT 1:
Reading the documentation, I found the concept of ValueTransformers, but didn't work either.

Ok, after fighting a while, I found a solution, which probably is not the only one.
I have created a StringTrimmerProfile.cs which implements AutoMapper.ITypeConverter<T, D>:
public class StringTrimmerProfile : ITypeConverter<string, string>
{
public string Convert(string source, string destination, ResolutionContext context)
{
return source == null ? null : source.Trim();
}
}
Then, on Startup.cs, in ConfigureServices(), I did the following:
services.AddAutoMapper(
cfg => cfg.CreateMap<string, string>().ConvertUsing(new StringTrimmerProfile())
);
By doing this, the Convert() method get's triggered for every model that contains a string.

Related

c# Minimum required of optional parameters

So I'm trying to get a list of relation existing between two table to validate some integration test.
The database is pretty simple : Table1 <- RelationTable -> Table2
I would like to get the existing relation from a list of Table1 Ids or a list of Table2 Ids or both.
If I said that my parameter are all optional, I need to verify that both aren't null or throw a exception if so. If I force both parameter and want to allow one or the other to be null, but not both, I need to create 3 methods to handle it or force the dev who will use the method to add null parameter in the call like the code below which I think it's a ugly way to do it.
Sadly this couldn't be polymorphism because the first params is the same type...
But I would like to allow methodX to just be call method and allow the 3 possible methods into one without allowing method() with no params to be use.
protected async Task<List<Relation>> method1(List<string> table1Ids) => method3(table1Ids, null);
protected async Task<List<Relation>> method2(List<string> table2Ids) => method3(null, table2Ids);
protected async Task<List<Relation>> method3(List<string> table1Ids, List<string> table2Ids)
{
if(table1Ids == null && table2Ids == null)
throw new ArgumentNullException();
// code here
}
To be honest, I could choose if all null throw or 3 method or for bulletproof code choose both and it would work fine, but I'm searching alternate version where I can force a minimum of one parameter but don't said which one is required. I thought maybe attribute from the .Net Framework would do that for me, but I couldn't find something near that. I'm searching for something that could do that out of the box or a custom attribute to do that.
It would be code something like that. Without the if throw because the attribute would validate it.
[MinimumOptionalRequiredAttribute(1)]
protected async Task<List<Relation>> GetRelationFromListOfIds(List<string> table1Ids = null,
List<string> table2Ids = null) {
// code here
}
// Example of code that could be use
{
// Those would work
var byTable1 = GetRelationFromListOfIds(table1Ids);
var byTable2 = GetRelationFromListOfIds(table2Ids:table2Ids);
var byTable1And2 = GetRelationFromListOfIds(table1Ids, table2Ids);
// This would not be allow by the c# intellisense
var throwException = GetRelationFromListOfIds();
}
I know I'm trying to solve everything with one method instead of going with a more "normal" way. I talk about attribute, but it not necessary an attribute. I would expect the code to not compile if you try call methodEmptyParamsNotAllow(). To be honest, I'm not even sure if that is a good idea for code readability. I'm just curious about the idea. Is something similar already exist? Is the idea good? What it would look like?

Add record to DbContext by returning null with a query

I did a research I not found anything so far. Appreciate your help.
As the title says, I'm adding a record to my DbContext by doing a query, and if it returns a null value then I create the record. Otherwise, I modify it.
My question is: Is this a good practice or I shouldn't do this that way? The code is like this:
var desiredEntity = MyDbContext.SingleOrDefault(x => x.Name == "Rob");
if (desiredEntity == null)
{ desiredEntity = new DbSetOfEntity()... //create if doesn't exists }
else
{ desiredEntity.ValueToModify == 3; }
MyDbContext.SaveChanges()
What is the difference between this and creating an entity explicitly and adding it with the DbContext.Add() method?
Edit:
A similar question here is asked, but I don't want to use AddOrUpdate method or Attach and changing the state of the entities manually. I just want to know if my approach is not problematic and what are the differences by using the conventional .Add(myEntity) approach.
AddOrUpdate() is checking record for existance by EntityKey. So if x.Name which you are checking is not Key - your approach is correct.
Also as you have only name value as an input parameter ("Rob") you will have to request record from context, and you will have it attached. So then you can just change it as you need and the changes will be tracked automatically. Alternatively, create it if it doesn't exist and call Add().
Taking into account the above your approach is OK and will work and I dont see any problems with it.
On the other hand, your code should be as simple and elegant as it can be. It is important for supporting your code by you or by your teammates. That is why using constructions like AddOrUpdate or other built-in stuff is good practice. But not a law.
P.S. I am not looking at code like { desiredEntity.ValueToModify == 3; }. This is potentially bad practice as 3 should perhaps be passed to your method as a parameter.

AutoMapper: almost always trim strings

So, following the advice of this answer, I've set up a string to trimmed string map in my base AutoMapper (3.3.1) config, as:
configuration.CreateMap<string, string>().ConvertUsing<StringToTrimmedStringConverter>();
Which works great, except for exactly like two fields in my database which need to preserve whitespace for interoperability reasons. Is there anything I can do in my data model to entity mapping to preserve whitespace when mapping between two string fields? I've tried:
.ForMember(d => d.WhitespaceField,
opts => opts.ResolveUsing<WhitespaceStringResolver>
(m => m.WhitespaceModelField))
where WhitespaceStringResolver is just a no-op:
public class WhitespaceStringResolver : ValueResolver<string, string>
{
protected override string ResolveCore(string source)
{
return source;
}
}
but that's not working. I can see execution hit the resolver but the strings wind up trimmed anyway.
Is there some way to ignore the base config's mapping and not trim the strings, just for the couple of fields I explicitly want to ignore it for?
Upgrading AutoMapper version is not something I want to do at this time.
What worked out in the end was adding
.AfterMap((model, entity) =>
{ entity.WhitespaceField = model.WhitespaceModelField; })
I could have also marked entity.WhitespaceField ignored, if I didn't need a field-to-field mapping around for a library that does searching using the model-to-entity mappings by convention.

Referencing ExportMetaData from within MEF-part?

This might be a super simple question, but since Google has a hard time giving me answers you might!
I'm wondering if its possible for a part in MEF to get hold of values defined in its own ExportMetadata?
Lets say I got this code for a part:
[ExportMetadata("name", "A Template Plugin")]
[ExportMetadata("guid", "0db79a169xy741229a1b558a07867d60")]
[ExportMetadata("description", "A template for a new plugin")]
[ExportMetadata("version", "1.0.0.43")]
[Export(typeof(IPlugin)), PartCreationPolicy(CreationPolicy.NonShared)]
public class PluginExport : IPlugin, IDisposable
{
... code goes here...
... can I get hold of metadata, ie the "guid" key ??? ...
}
If anyone questions the sanity of this its bcause Im making a plugin template for 3pp developers and some values (not shown in the example above) also needs to be used from within the plugin and I think it would be nice not having them setup a lot of data in two separate places.
You can use reflection regardless of MEF to get the attribute value:
[ExportMetadata("guid", "0db79a169xy741229a1b558a07867d60")]
class PluginExport
{
void PrintGuid()
{
var guid = this.GetType()
.GetCustomAttributes(false)
.OfType<ExportMetadataAttribute>()
.Single(attribute => attribute.Name == "guid").Value;
Console.WriteLine(guid); // Prints your value.
}
}

Best way to access attributes

I am working on a framework that uses some Attribute markup. This will be used in an MVC project and will occur roughly every time I view a specific record in a view (eg /Details/5)
I was wondering if there is a better/more efficient way to do this or a good best practices example.
At any rate, I have an a couple of attributes e.g:
[Foo("someValueHere")]
String Name {get;set;}
[Bar("SomeOtherValue"]
String Address {get;set;}
What is the most efficient way/best practice to look for these attributes/Act on their values?
I am currently doing something like this:
[System.AttributeUsage(AttributeTargets.Property)]
class FooAttribute : Attribute
{
public string Target { get; set; }
public FooAttribute(string target)
{
Target = target;
}
}
And in my method where I act on these attributes(simplified example!):
public static void DoSomething(object source)
{
//is it faster if I make this a generic function and get the tpe from T?
Type sourceType = source.GetType();
//get all of the properties marked up with a foo attribute
var fooProperties = sourceType
.GetProperties()
.Where(p => p.GetCustomAttributes(typeof(FooAttribute), true)
.Any())
.ToList();
//go through each fooproperty and try to get the value set
foreach (var prop in fooProperties)
{
object value = prop.GetValue(source, null);
// do something with the value
prop.SetValue(source, my-modified-value, null);
}
}
Attribute.GetCustomAttribute and PropertyInfo/MemberInfo.GetCustomAttribute is the recommended way of getting at attribute objects.
Although, I wouldn't normally enumerate all properties with attributes; you generally want to work a particular attribute so you'd just call GetCustomAttribute directly.If you're looking for attributes on any of your properties, enumerating those properties looking for attributes based on GetCustomAttribute() the way you're doing it, is the best way to do it.
There is not really much choice when dealing with attributes - your code is ok and reasonable as is, it is also unlikley to be your main performance concern. The only immediate thing is to drop ToList call as absolutely unnecessary.
Side notes: performance related question should look approximately
"I've measured my code and portion XXX seems to be taking too much time (YYY) . The time goal for this piece of code is ZZZ. Is my way of doing XXX reasonable/where can I improve it?".
Note that in you case you are missing YYY and ZZZ time portions - so you can't really say if it is slow for your case or not. And you may want to start measurements with DB/other IO bound operations as it more likely to speed up your overall code.
After you figured that this attribute related code is main perfomance issue you can consider some sort of caching of results or even code generation of some sort (either through caching lambdas that would set necessary values or even full blown IL generation).

Categories

Resources