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 _logger; public HomeController(ILogger logger) { _logger = logger; } public string Index() { var metadata = this.HttpContext.RequestServices.GetRequiredService().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)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)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 }); } } }