Configure Swashbuckle (OpenAPI) to Ignore Namespace in Models - asp.net-core

On the generated swagger page in the Model section, how does one get Swashbuckle to not report the whole namespace, but just the model?
MyNamespace.SubFolder.MyModel
to
MyModel

You should be able to define custom schema id's either through an ISchemaFilter
or create your own "schema id strategy" read: Customizing Schema Id's
services.AddSwaggerGen(c =>
{
...
c.CustomSchemaIds((type) => type.FullName);
};
You could create a base model class that contains a name property (remember to [JsonIgnore]) use that property for the strategy.

Related

Change column name for non-primitive field (navigation) with EF Core

Given the following classes:
public class Mission
{
private MissionCard _missionCard;
}
public class MissionCard
{
}
I would like to create this relationship via Fluent API so that _missionCard is treated as a relationship and can be populated from DB but isn't available as a property on my Mission model.
I can create that relationship with:
modelBuilder.Entity<Mission>().HasOne<MissionCard>("_missionCard");
but by default this creates a FK column named "_missionCard". The docs show that a custom name can be specified when using .Property("property name").FromField("field name") but you cannot use .Property for non-primitive types.
Is it possible to change the column name for a relationship like above?
Managed to resolve this by inverting the relationship:
modelBuilder.Entity<MissionCard>()
.HasMany<Mission>()
.WithOne("_missionCard")
.HasForeignKey(nameof(MissionCard));

Single resource file for DataAnnotations localization

What I should try to achieve is to have a single resource (resx) file for each supported language in net-core. I explain the problem a bit.
I have DataAnnotations on each of my entities and I need to localize the messages returned in case of errors. It seems that the default convention required by net-core is to have a different resx file for each of our entities.
This file is named accordingly to the namespace of the entity with the culture indentifier and the resx extensions. So, if I have an entity named Customers within the namespace Data.Entities, I should add a file named Data.Entities.Customers.it.resx and put all the translations for the Italian language in it. So, if I have an attribute
StringLength(50, ErrorMessage="The {0} should not be longer than {1} characters")
public string Name {get;set;}
then I add the proper translation to the Data.Entities.Customers.it.resx file.
But, if I go on another entitity like Suppliers I am forced to write another resource file named Data.Entities.Suppliers.it.resx and, of course I have
StringLength(50, ErrorMessage="The {0} should not be longer than {1} characters")
public string SupplierName {get;set;}
Now I need to write again the same translation in the proper file for the Suppliers entity. This goes on as well for other common attributes like [Required].
So I hope to have explained well my problem and my queston is: There is a way to specify a single resource file for all my entities validation messages and then write a single time the messages for the common texts?
From the docs, you can tell the framework to use a shared resource for your data annotations localisation:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddDataAnnotationsLocalization(options => {
options.DataAnnotationLocalizerProvider = (type, factory) =>
factory.Create(typeof(SharedResource));
});
}
In the preceeding code, SharedResource is the class corresponding to the resx where your validation messages are stored. With this approach, DataAnnotations will only use SharedResource, rather than the resource for each class.

Updating and inserting in an OData service

I have a Xamarin.Forms Visual Studio solution, into which I installed the “Simple.OData.Client” package with NuGet. I have the URI of an OData service and I want to load items from the table “Persons”, in which the base element type is “Person” and which contains instances of the class “Customer”, which inherits from the class “Person”, as I can see when opening the URI to which I append “/$metadata”.
<Schema xmlns="http://schemas.microsoft.com/ado/2009/11/edm" Namespace="A">
...
<EntityType Name="Person" Abstract="true">
...
<EntityType Name="Customer" BaseType="A.Person">
...
<EntityContainer Name="Model" m:IsDefaultEntityContainer="true">
...
<EntitySet Name="Persons" EntityType="A.Person"/>
...
I create an instance of the service:
ODataClient clientSimple = new ODataClient("http://.../.../odata.v3/default");
I load items from the data table:
System.Collections.Generic.IEnumerable<System.Collections.Generic.IDictionary<string, object>> persons = await clientSimple.For("Persons").FindEntriesAsync();
The items are returned as dictionaries where the keys are the property names and the values are the property values. I see that the properties from the “Person” entity type as well as those added in the derived “Customer” type are present.
I know that there is also a possibility of the typed syntax:
var personsTyped = await clientSimple.For<Person>().FindEntriesAsync();
However, I do not know where to get the definition of the “Person” class so that I can use it here as the generic type parameter.
Then I want to modify an entry in the OData service:
await clientSimple.For("Persons").Key(1).Set(new { FirstName = "Johnny" }).UpdateEntryAsync();
This works as long as I only update a property defined in the “Person” entity type, but trying to modify a property added in the “Customer” entity type raises an exception:
await clientSimple.For("Persons").Key(1).Set(new { FirstName = "Johnny", SalesPerson = "..." }).UpdateEntryAsync();
[Simple.OData.Client.UnresolvableObjectException] No property or association found for [SalesPerson].
Trying to insert a new item also fails:
var newObjectCreated = await clientSimple.For("Persons").Set(new { FirstName = "...", ... }).InsertEntryAsync();
[Simple.OData.Client.WebRequestException] Internal Server Error
How can I solve this so that I can update all properties and insert new items?
There are several source of information that might be useful for you. First, I suggest you have a look at Simple.OData.Client wiki pages, in particulary pages that give examples of how to modify data:
https://github.com/object/Simple.OData.Client/wiki/Modifying-data
Then there are plenty of examples that you can get from the project tests, look here for example:
https://github.com/object/Simple.OData.Client/blob/master/Simple.OData.Client.Tests.Net40/InsertTests.cs
https://github.com/object/Simple.OData.Client/blob/master/Simple.OData.Client.Tests.Net40/InsertTypedTests.cs
https://github.com/object/Simple.OData.Client/blob/master/Simple.OData.Client.Tests.Net40/UpdateTests.cs
https://github.com/object/Simple.OData.Client/blob/master/Simple.OData.Client.Tests.Net40/UpdateTypedTests.cs
And if you want to use typed syntax (which I recommend) you should define your entity types yourself, currently Simple.OData.Client doesn't have any entity type generation utility.

NHibernate mapping by code: Mapping userTypes by convention

I would like to know how to configure NHibernate "mapping by code" so that when I map a property of a certain type, it uses a certain userType to perform that mapping. It figures this out by convention.
For example, if I have an Account class with a property Currency of type Currency, then the NHibernate configuration should figure out (by convention) that it needs to use the CurrencyUserType to perform the mapping.
I'm unable to find the relevant documentation for this, so if such documentation does exist, then a few links will be appreciated too.
Note: This is not a FluentNHibernate question.
var mapper = new ConventionModelMapper();
mapper.IsProperty((info, b) => b || info.GetPropertyOrFieldType() == typeof(Currency));
mapper.BeforeMapProperty +=
(inspector, member, customizer) =>
{
if (member.LocalMember.GetPropertyOrFieldType() == typeof(Currency))
customizer.Type<CurrencyUserType>();
};

creating base model class in yii

In my application, i have fields that are common to all tables, like create date, update date etc. To assign these values i'm using beforeValidate callback. Now, this callback is same for all models.
To avoid code duplication, i want to create a base model class.
But, when I tried to create a base model, yii thrown error saying table cannot be found in database, which is true since I dont have any table for this base model.
Is there any way I can create a base model class.
Yes, if you work with dynamic DB structure or have other reasons to work with Yii ActiveRecord without creating classes for each table in DB, you may use smartActiveRecord yii extension
I separated it few minuts ago from my other extension -- AR behavior that adds versioning to any model (it copies all data on insert & update to special table (and create it if it's absent), that have a same structure as source table + "revision field" and primary key extended by this field.
Look at SmartAR.php source, there is example of usage in comments.
Take a look at CTimeStampBehavior.
Incase that doesn't help you, you can just write a behavior class yourself.
Hope this helps.
Edit:Assuming you are using ActiveRecords.
If you want to create a new base model, you can do this:
abstract class MyBaseARClass extends CActiveRecord{
protected function beforeValidate(){
if(parent::beforeValidate()){
// assign your fields
return true;
}
else return false;
}
}
Have you created a base table? Thinking about the Yii framework it may be easier to have a relationship between a model and the base model.
In your case, you need to override
public static function model($className=__CLASS__)
{
return parent::model($className);
}
in every child class so Yii would know which table to use for your model. Otherwise it will try and use base class as table name.
I.e.
class User extends BaseActiveRecord {
public static function model($className=__CLASS__)
{
return parent::model($className);
}
}