webAPI serialise enums to strings - webapi

This doesn't do it
[JsonConverter(typeof(StringEnumConverter))]
public enum Numbers
{
[EnumMember(Value = "[")]
One,
[EnumMember(Value = "Two")]
Two
}
And nor does this on the POCO/DTO.
[JsonProperty(ItemConverterType = typeof(StringEnumConverter))]
public IEnumerable<Numbers> Numbers{ get; set; }
Why is this impossible?

So it turns out that out of the box it uses some JSON thing that isn't Newtonsoft and which ignores the Newtonsoft attributes. How very crap.
The fix is to install NuGet package Microsoft.AspNetCore.Mvc.NewtonsoftJson and in Startup.ConfigureServices to add:
services.AddControllersWithViews().AddNewtonsoftJson();

Related

Crash when using Double? property in SQLIte in Blazor Wasm (.Net6)

I'm using Blazor Wasm with a SQLite clientdatabase. Like here (https://github.com/dotnetnoobie/BlazorAppSqlite)
public DbSet<Test> Tests { get; set; } = default!;
.....
public class Test
{
[Key]
public int Id { get; set; }
public double? NullableDoubleValue { get; set; }
}
......
var test = new Test();
test.Id = 1;
test.NullableDoubleValue = 1;
_appState.ClientSideDbContext.Tests.Add(test);
await _appState.ClientSideDbContext.SaveChangesAsync();
When the last line is executed, the Blazor app wil crash.
With this error in the log:
/__w/1/s/src/mono/mono/mini/aot-runtime-wasm.c:113
/__w/1/s/src/mono/mono/mini/aot-runtime-wasm.c:113
Uncaught ExitStatus
What change do I have to make to use a (nullable) double?
The issue seems to come from using float or double. The fix has been merged and it will probably be released with dotnet 7 as mentioned in this issue.
Description
Seeing a bug when using SQLitePCL.Raw preview and also see the same bug in Steve Sandersons Blaze Orbital sample when using double/float in entity classes. Works fine with decimals! Tried with EF Core and SQLite-net.
As a workaround, you can use decimal instead of float or double and it will work just fine.

Properties Added with Aspects Not in Generated JSON Schema

I'm trying to generate JSON Schemas using Newtonsoft JSON Schema. Regular properties added in my POCO class are added to the schema when it is generated. I'm also using PostSharp Aspects to add properties, but none of those are added to the schema.
This is a Console application targeting .NET 4.7.2.
Here is my Console application:
public class Program
{
private static void Main(string[] args)
{
JSchemaGenerator gen = new JSchemaGenerator();
JSchema schema = gen.Generate(typeof(MyClass));
File.WriteAllText("C:\\Temp\\TestSchema.json", schema.ToString());
}
}
Here is my aspect:
[PSerializable]
public class TestAspect : InstanceLevelAspect
{
[IntroduceMember]
[JsonProperty(Required = Required.Always)]
public string AspectProp { get; set; }
}
And here is my POCO:
[TestAspect]
public class MyClass
{
public int MyProperty { get; set; }
}
Finally, here is the generated schema:
{
"type": "object",
"properties": {
"MyProperty": {
"type": "integer"
}
},
"required": [
"MyProperty"
]
}
The MyProperty property is in the schema, but AspectProp - the property added by the aspect - is not.
When I open the exe in a decompiler, I can see that AspectProp is actually added to MyClass:
I'm not sure if this is a problem with PostSharp or Newtonsoft JSON Schema or if I'm doing something wrong. It seems like this should be possible.
Edit 1: 20 May
I split my solution out into separate projects - one for the Console app, one for the Aspect and one for MyClass. After making sure I was referencing the generated MyClass DLL directly (i.e. not a project reference, I actually removed the project once MyClass was built) it did not make a difference. AspectProp is still not in the schema. Based on this and the serialization suggested below by #dbc, this leads me to believe it is a problem with the Newtonsoft schema generator
Edit 2: 20 May
Per Antonin's Answer below, I created a new ContractResolver:
public class AspectPropertyResolver : DefaultContractResolver
{
public AspectPropertyResolver()
{
SerializeCompilerGeneratedMembers = true;
}
}
And then registered it in my app before calling Generate:
gen.ContractResolver = new AspectPropertyResolver();
Now my schema includes the aspect-generated property.
Newtonsoft.Json has an opt-in feature to serialize compiler-generated properties. See Newtonsoft.Json.Serialization.DefaultContractResolver.SerializeCompilerGeneratedMembers property.

OrmLite - GUIDs as primary keys in Oracle

I'm using OrmLite with both SqlServer, Oracle and PostgreSQL dialects.
I want to use GUIDs as primary keys and have a simple object, using the AutoId attribute:
public class MyObject
{
[AutoId]
public Guid Id { get; set; }
[Required]
public string Name { get; set; }
...
All goes well with SqlServer and PostgreSQL dialetcs, but with Oracle I get an initial GUID with all zeros in the db, and a subsequent INSERT violates the unique key constraint of my primary key. How can this be accomplished db agnostic so it also works with Oracle?
Based on the source code I'm looking at, it doesn't appear to properly generate GUIDs for anything that's not SQL Server or PostgreSQL, regardless of what the documentation actually says on the README. Relevant code links below:
SQL Server
PostgreSQL
Base Dialect Provider
The best alternative I can provide here is to override the OracleOrmLiteDialectProvider. Specifically, I would override the GetAutoIdDefaultValue method to return "SYS_GUID()" if the field type is a GUID. Sample code below...
public OracleNewGuidOrmLiteDialectProvider : OracleOrmLiteDialectProvider
{
public static OracleNewGuidOrmLiteDialectProvider Instance = new OracleNewGuidOrmLiteDialectProvider();
public string AutoIdGuidFunction { get; set; } = "SYS_GUID()";
public override string GetAutoIdDefaultValue(FieldDefinition fieldDef)
{
return fieldDef.FieldType == typeof(Guid)
? AutoIdGuidFunction
: null;
}
}
To match the rest of the provider implementations, I would recommend creating a OracleNewGuidDialect class, like below...
public static class OracleNewGuidDialect
{
public static IOrmLiteDialectProvider Provider => OracleNewGuidOrmLiteDialectProvider.Instance;
}
Then you would set the provider when you instantiate your OrmLiteConnectionFactory to OracleNewGuidOrmLiteDialectProvider.Instance, similar to below...
var dbFactory = new OrmLiteConnectionFactory(oracleConnectionString, OracleNewGuidDialect.Provider);
This isn't the best solution, but the pluggable nature of ServiceStack ORMLite allows you to control everything to the extent that you need. Hope this helps. Also, quick caveat--I didn't fully bake this solution, so you may need to tweak it, but based on the other implementations of the providers, it seems straightforward.

How to add validation to my POCO(template) classes

So I used this tutorial to generate my poco classes which I am to use throughout my aplication.. the problem is that Im not supposed to modify the generated cs files cause they get autoregenerated... How do I add attributes like [Required] and stuff like that?? please help
You can't add it directly (unless you modify T4 template to create them for you) but you can try to use trick introduced in ASP.NET dynamic data. All POCO classes are defined as partial. So lets define your partial part:
using System.ComponentModel.DataAnnotations;
[MetadataType(typeof(MyClassMetadata))]
public partial class MyClass
{
private class MyClassMetadata
{
[Required]
public object Id;
[Required]
[StringLength(100)]
public object Name;
}
}
Metadata class is special type to hold only metadata - it is never used. Name of fields must be same as corresponding fields in real class (field types doesn't matter so you can use object).
Anyway in ASP.NET MVC you should use specialized View model for each view and pass data you need so the validation attributes will be placed in view model class.
The attributes on the generated POCOs are derived from the facets on the entities in the model. e.g. for [Required] make sure the field is "not null" and for [StringLength(n)] make sure the datatype is nvarchar(n) via the MaxLength facet.
Further expanding on the answer. By using Microsoft Patterns & Practices Enterprise Library 5 Validation Block, you can open up a wealth of validation possibilities beyond those available through normal data annotations.
using Microsoft.Practices.EnterpriseLibrary.Validation;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;
[HasSelfValidation]
public partial class Category : ICategory
{
[SelfValidation]
public void Validate(ValidationResults validationResults)
{
if (this.Title === "Credo")
{
validationResults.AddResult(
new ValidationResult(
"Category title cannot be a veiled reference to a former cool 2000AD character.",
this,
null,
null,
null));
}
validationResults.AddAllResults(
ValidationFactory
.CreateValidator<ICategory>()
.Validate(this));
}
}
using System;
using System.ComponentModel.DataAnnotations;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;
public interface ICategory
{
int Id
{
get;
set;
}
[Required]
[StringLengthValidator(1, 50, MessageTemplate = "Category title should be a maximum of 50 characters in length.")]
string Title
{
get;
set;
}
}

Generate a form from a poco object

Say you had a config object
public class MyConfig{
public int PageSize{get;set;}
public string Title{get;set;}
}
and you want to automatically generate a asp.net form to edit the properties on this object.
Do you know of any frameworks to do this automagically?
I know of MS Dynamic data, but seems I need to have the whole stack (database, linq, objects) to get this up and running. So I was thinking of something simpler..
Sorry for jumping in late. There are several ways to use Dynamic Data with POCO.
Use the DynamicObjectDataSource which is found in Futures and Preview releases of Dynamic Data, starting with July 2008 Futures. When looking in a Preview release, it contains a Futures assembly, Microsoft.Web.DynamicData.dll.
When using ASP.NET 4.0 (now in Beta), you can call a new extension method, EnableDynamicData(). See the "SimpleDynamicDataSamples" project that comes with DD Preview 4 and later.
Here's an example from that code that uses an ObjectDataSource and the POCO class called "Product".
[MetadataType(typeof(Product.Metadata))]
public partial class Product {
public class Metadata {
[Required]
public string ProductName { get; set; }
[Range(0, 100)]
public decimal UnitPrice { get; set; }
}
}
public partial class ObjectDataSourceSample : System.Web.UI.Page {
protected void Page_Init() {
// Extension method syntax
ProductsList.EnableDynamicData(typeof(Product));
// Explicit syntax
// MetaTable table = MetaTable.CreateTable(typeof(Product));
// MetaTable.MapControl(ProductsList, table);
// ProductsList.ColumnsGenerator = new DefaultAutoFieldGenerator(table);
}
}
I was under the impression that you could modify the T4 templates used by dynamic data (Not sure if you can remove the data access part).
Have you looked at just using T4 on its own.

Resources