Breeze Web API with very simple table per hierarchy inheritance structure - c#

This post (https://stackoverflow.com/a/14486260/894358) suggests that Breeze does support inheritance, but my breeze manager is not able to understand the metadata being returned from the API. The server will return metadata and JSON results from other action methods, but when the manager tries to interpret the metadata it throws the error: "Cannot read propertyRef of undefined".
Here is my very simple implementation (Code First Migrations generates the database):
namespace VerySimpleVehicleModel.Models
{
public abstract class Vehicle
{
public int Id { get; set; }
public int Speed { get; set; }
}
public class Bus: Vehicle
{
public int Capacity { get; set; }
}
public class Car : Vehicle
{
public string Color { get; set; }
}
public class VehicleContext : DbContext
{
public DbSet<Car> Cars { get; set; }
public DbSet<Bus> Buses { get; set; }
public DbSet<Vehicle> Vehicles { get; set; }
}
}
namespace VerySimpleVehicleModel.Controllers
{
[BreezeController]
public class BreezeController : ApiController
{
readonly EFContextProvider<VehicleContext> _contextProvider = new EFContextProvider<VehicleContext>();
[HttpGet]
public string Metadata()
{
return _contextProvider.Metadata();
}
[HttpGet]
public IQueryable<Car> Cars()
{
return _contextProvider.Context.Cars;
}
}
}
And here is the metadata returned from the Metadata action method:
"{
\"schema\":
{
\"namespace\":\"VerySimpleVehicleModel.Models\",
\"alias\":\"Self\",
\"d4p1:UseStrongSpatialTypes\":\"false\",
\"xmlns:d4p1\":\"http://schemas.microsoft.com/ado/2009/02/edm/annotation\",
\"xmlns\":\"http://schemas.microsoft.com/ado/2009/11/edm\",
\"cSpaceOSpaceMapping\":\"
[
[
\\\"VerySimpleVehicleModel.Models.Vehicle\\\",
\\\"VerySimpleVehicleModel.Models.Vehicle\\\"
],
[
\\\"VerySimpleVehicleModel.Models.Car\\\",
\\\"VerySimpleVehicleModel.Models.Car\\\"
],
[
\\\"VerySimpleVehicleModel.Models.Bus\\\",
\\\"VerySimpleVehicleModel.Models.Bus\\\"
]
]
\",\"entityType\":
[
{
\"name\":\"Car\",
\"baseType\":\"Self.Vehicle\",
\"property\":
{
\"name\":\"Color\",
\"type\":\"Edm.String\",
\"fixedLength\":\"false\",\"maxLength\":\"Max\",
\"unicode\":\"true\",\"nullable\":\"true\"
}
},
{
\"name\":\"Bus\",
\"baseType\":\"Self.Vehicle\",
\"property\":{\"name\":\"Capacity\",
\"type\":\"Edm.Int32\",\"nullable\":\"false\"}
},
{
\"name\":\"Vehicle\",
\"abstract\":\"true\",
\"key\":{\"propertyRef\":{\"name\":\"Id\"}},
\"property\":
[
{\"name\":\"Id\",\"type\":\"Edm.Int32\",\"nullable\":\"false\",\"d4p1:StoreGeneratedPattern\":\"Identity\"},
{\"name\":\"Speed\",\"type\":\"Edm.Int32\",\"nullable\":\"false\"}
]
}
]
,\"entityContainer\":
{
\"name\":\"VehicleContext\",
\"entitySet\":
{
\"name\":\"Vehicles\",
\"entityType\":\"Self.Vehicle\"
}
}
}
}"

I can't reproduce a problem with your example. In fact, it works like a charm.
I copied it almost verbatim to the DocCode sample because it is so simple and we needed a simple one before getting into the complexities of the BillingDetails example (will publish next release).
This is a standard TPH model with an abstract base class. The key is recognized in metadata; look at the Vehicle base class for this line:
\"key\":{\"propertyRef\":{\"name\":\"Id\"}},
What is odd is that you are receiving metadata in the old string format. When I look at the payload for the metadata in my test runs I get a JSON object:
{"schema":{"namespace":"Inher ...
"entityType":[{"name":"Vehicle",
"abstract":"true",
"key":{"propertyRef":{"name":"Id"}}, ...
}]}]}}}
I suspect that you have an old copy of the Breeze.WebApi.dll. Perhaps you updated the Breeze NuGet package and the old assembly got trapped in the references or an old script file was retained. Try uninstalling and re-installing Breeze. Look carefully at the NuGet console log to make sure everything was replaced.

Related

Generate JsonSchema from a class hierarchy in C#

I have a class hierarchy that I want to serialize to json in a tagged union in an array.
class BaseComponent
{
public string Id { get; set; }
}
class Child1: BaseComponent
{
public string Child1Prop { get; set; }
}
class Child2: BaseComponent
{
public string Child2Prop { get; set; }
}
class Wrapper
{
public List<BaseComponent> Components { get; set; }
}
Sample json
{
"components": [
{
"id": "id-1",
"type": "Child1",
"child2Prop": "Hello"
},
{
"id": "id-2",
"type": "Child2",
"child2Prop": "world"
},
]
}
The hierarchy is likely to change, and I want to publish a nice Json Schema for validation and manual editing of the json files in VSCode. Is there any reasonable tools that lets me generate this? Or even just some strongly typed json schema C# classes that i can use to create the schema from reflection.
My Nuget package JsonSchema.Net.Generation is built for generating schemas from C# code.
The docs and a playground can be found on https://json-everything.net/json-schema

ModelStateDictionary alternative

I'm trying to build an alternative of ModelState as when I return this from api like return BadRequest(ModelState) it doesn't have much information other than somethings gone wrong with the request. So I have decided to build an alternative which will eventually look like this:
{
"code": 1000,
"message": "Invalid request",
"fields": [
{
"name": "Password",
"message": "Password does not meet complexity requirements."
}
]
}
In order to accomplish this, I have the following models in my api project:
ErrorResponse.cs:
public class ErrorResponse
{
public string Code { get; set; }
public string Message { get; set; }
public Dictionary<string, Field> Fields { get; set; }
}
Field.cs:
public class Field
{
public string Name { get; set; }
public string Message { get; set; }
}
Thanks to using FluentResults I can determine the error from the service layer within my controller like so:
if (result.HasError<PasswordError>())
{
}
However I've realised that I now need to return the ErrorResponse but each Field has a name and the only way to know the name of the field is through the controller using:
nameof(RegisterRequest.Password)
Is there a way to do this in a clean generic way without using magic strings?

Deserialize json into python like Dictionary with C#

I need to write a dynamically typed system in a statically typed language using the System.Text.Json lib in .net core 3.1. What I need is to deserialize files into a Python like dict. I have to use C# for this because we can't get python to authenticate against our systems correctly. And C# is our default lang, so...
In the real world, these documents are in CosmosDB. This program takes in a configuration file that points to specific fields in document structures and it has to inspect those fields, maybe update them, then write the result back to the CosmosDB. Currently, I'm building a system that points to the specific field. Since the system has no clue what the structure of the doc is that it's getting back from the cosmos, it can't use formal models. I am currently working on the system that inspects or updates the fields using static files in the test suite. I'll worry about cosmos DB when this is finished.
Take this file for example:
{
"azureSql": {
"databaseName": "ordersdb",
"tables": [
{
"tableName": "mytable",
"columnNames": [
"column1",
"column2"
]
}
]
},
"cosmosDb": {
"databaseName": "CosmosDb",
"collections": [
{
"collectionName": "TestCollection",
"fieldNames": [
"MyStatus.json.path.to.field"
]
}
]
}
}
files like this get read in. The input can be virtually any type of legit json. I need to put that into a Dictionary that I can access similar to Python mydict["cosmosDb"]["collections"][0]["fieldNames"]
The line:
_entities = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonString);
doesn't work because it only serializes the first level. The rest are json entry types.
I found this C# way to mimic Python Dictionary Syntax
and its close, but it only supports string and doesn't work in the Deserialize method.
Any ideas on how to solve this?
I suggest you to use dynamic
var entities = JsonSerializer.Deserialize<dynamic>(jsonString)
Would the following classes structure work?
public class Rootobject
{
public Azuresql azureSql { get; set; }
public Cosmosdb cosmosDb { get; set; }
}
public class Azuresql
{
public string databaseName { get; set; }
public List<Table> tables { get; set; }
}
public class Table
{
public string tableName { get; set; }
public List<string> columnNames { get; set; }
}
public class Cosmosdb
{
public string databaseName { get; set; }
public List<Collection> collections { get; set; }
}
public class Collection
{
public string collectionName { get; set; }
public List<string> fieldNames { get; set; }
}
Edit:
This works:
using Newtonsoft.Json.Linq;
var result = JObject.Parse(jsonFile);
var detail = result["cosmosDb"]["collections"][0]["collectionName"];

Which type should be a free json field in a DTO in C# dotnet core?

I receive a free form JSON field, which I do not need to touch. My service simply saves it in a DB (the other fields are important, but this one has nothing to do with the logic. The client can put anything in it).
Example:
Body = {
title: myTitle,
stuff: {can be any json}
}
How should I map this to a DTO class?
Example:
public class MyDto(){
public string Title { get; set; }
public ?????? Stuff { get; set; }
I tried using "string", but it does not work (the whole body is received as null, as it does not understand that it's the correct DTO type).
My current idea is to go with the "dynamic" type, would that be a good idea?
I'm looking for best practices.
You could use dynamic and the JSON.NET library:
https://weblog.west-wind.com/posts/2012/aug/30/using-jsonnet-for-dynamic-json-parsing
You should use a System.Json.JsonElement to represent a generic Json node as exemplified bellow.
public class HomeController : ControllerBase
{
public class InputDTO
{
public string Title { get; set; }
public System.Text.Json.JsonElement Stuff { get; set; }
}
[HttpPost]
[Route("")]
public void Post([FromBody] InputDTO data)
{
var rawSuffJson = data.Stuff.ToString();
}
}
The HTTP request body can be like this:
{
"title": "My Title",
"stuff": {
"str": "String",
"int32": 1,
"list": [ 1,2,3 ]
}
}

How to list all minecraft profiles

How to list all minecraft profiles by launcher_profiles.json file?
I tried to use the site json2csharp.com, but unfortunately when it generated the class ready code he has returned all the profiles as if it were also a class.
for example:
I used this simple code minecraft profile file ...
{
"profiles": {
"1.7.10": {
"name": "1.7.10",
"lastVersionId": "1.7.10"
}
},
"selectedProfile": "1.7.10"
}
But when I send the site to convert C# it returns this:
public class __invalid_type__1710
{
public string name { get; set; }
public string lastVersionId { get; set; }
}
public class Profiles
{
public __invalid_type__1710 __invalid_name__1.7.10 { get; set; }
}
public class RootObject
{
public Profiles profiles { get; set; }
public string selectedProfile { get; set; }
}
See for yourself: Json2CSharp
Have you any way I can read the launcher_profiles.json file minecraft using Newtonsoft.Json.Linq?
While useful in many cases, json2csharp.com is not foolproof. As you've seen, it does not handle cases where key names are dynamic or otherwise cannot be converted into valid C# identifiers. In these cases you will need to make manual adjustments to the generated classes. For example, you can use a Dictionary<string, Profile> in place of a static class to handle the dynamic keys of the profiles object.
Define your classes like this:
public class RootObject
{
public Dictionary<string, Profile> profiles { get; set; }
public string selectedProfile { get; set; }
}
public class Profile
{
public string name { get; set; }
public string lastVersionId { get; set; }
}
You can then deserialize into the RootObject class using either JavaScriptSerializer or Json.Net, whichever you prefer.
Here is a fiddle using Json.Net: https://dotnetfiddle.net/ZlEK63
So the problem may be that the launcher_profiles.json is not really kosher JSON.
Put this into Json2CSharp to see what I mean:
{
"profiles": [
{
"name": "1.7.10",
"lastVersionId": "1.7.10"
}
],
"selectedProfile": "1.7.10"
}
The difference here is that I've redefined the profiles node to correctly represent a collection (array) that's mapped to a generic list in C#.
You may need to manually parse that file as JSON.Net or other options will not be able to work with the invalid json format.
I generally don't work with the Linq versions of the Json.Net library, but I've come up with a simple example of how to get all of the names of the profiles (you can't serialize to a class with the given format).
class Program
{
//Add another "profile" to show this works with more than one
private static String json = "{ \"profiles\": { \"1.7.10\": { \"name\": \"1.7.10\", \"lastVersionId\": \"1.7.10\" }, \"1.7.11\": { \"name\": \"1.7.11\", \"lastVersionId\": \"1.7.11\" } }, \"selectedProfile\": \"1.7.10\" }";
static void Main(string[] args)
{
//Parse to JObject
var obj = Newtonsoft.Json.Linq.JObject.Parse(json);
foreach (var profile in obj["profiles"])
{
foreach (var child in profile.Children())
{
Console.WriteLine(child["name"]);
}
}
}
}

Categories

Resources