You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
iot/labs/CSharpObjectJsonSchema/Controllers/HomeController.cs

124 lines
4.8 KiB

using CSharpObjectJsonSchema.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Dynamic;
using System.Linq;
using System.Reflection;
namespace CSharpObjectJsonSchema.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public string Index()
{
var metadata = this.HttpContext.RequestServices.GetRequiredService<IModelMetadataProvider>().GetMetadataForType(new TestModel().GetType()) as DefaultModelMetadata;
var json = CreateJson(metadata);
return JsonConvert.SerializeObject(json, Formatting.Indented);
}
private object CreateJson(DefaultModelMetadata metadata)
{
try
{
dynamic json = new ExpandoObject();
var dictionary = (IDictionary<string, object>)json;
//type
if (metadata.IsComplexType && metadata.IsCollectionType)
{
json.type = "array";
json.items = new { type = metadata.ModelType.GenericTypeArguments[0].Name };
}
else if (metadata.IsNullableValueType)
{
json.type = metadata.ModelType.GenericTypeArguments[0].Name;
}
else
{
json.type = metadata.ModelType.Name;
}
if (!metadata.IsComplexType && !metadata.IsNullableValueType && metadata.ModelType != typeof(string))
{
json.required = true;
}
if (metadata.DisplayName != null)
{
json.title = metadata.DisplayName;
}
foreach (var attribute in metadata.Attributes.Attributes)
{
if (attribute is DescriptionAttribute descriptionAttribute)
{
json.description = descriptionAttribute.Description;
}
else if (attribute is RegularExpressionAttribute regularExpressionAttribute)
{
json.pattern = regularExpressionAttribute.Pattern;
}
else if (attribute is RequiredAttribute requiredAttribute)
{
json.required = true;
}
//
else if (attribute is CompareAttribute compareAttribute)
{
json.compare = compareAttribute.OtherProperty;
}
else if (attribute is RemoteAttribute remoteAttribute)
{
var routeData = attribute.GetType().GetProperty("RouteData", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(remoteAttribute) as RouteValueDictionary;
json.remote = new
{
url = Url.Action(routeData["action"].ToString(), routeData["controller"].ToString(), new { Area = routeData["area"].ToString() }),
remoteAttribute.AdditionalFields,
//remoteAttribute.
};
}
}
dynamic properties = new ExpandoObject();
var propertiesDictionary = (IDictionary<string, object>)properties;
if (metadata.IsComplexType && !metadata.IsCollectionType && metadata.Properties.Any())
{
foreach (var item in metadata.Properties)
{
propertiesDictionary[item.PropertyName] = CreateJson(item as DefaultModelMetadata);
}
json.properties = properties;
}
return json;
}
catch (Exception ex)
{
return null;
}
//Console.WriteLine(metadata.DataTypeName);
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
}
}