How to deserialize luis entity in IRecognizerConvert - c#

In Luis, I created a simple pattern with a simple entity like this:
list bots {Name}
where "Name" is my entity that I would like to get in C#. The pattern and intent works fine and I am getting that correctly.
I follow the official example and built a IRecognizerConvert class so I can deserialize the result. It deserialize the intent just fine but fail to deserialize the entity.
In the _Entities sub-class, I only have the "Name" variable that I am trying to deserialize and nothing else. I don't have any other partial class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Bot.Builder;
using Newtonsoft.Json;
using Microsoft.Bot.Builder.AI.Luis;
namespace EmptyBot1.Models
{
public class ChatbotIntent : IRecognizerConvert
{
public string Text;
public string AlteredText;
public enum Intent
{
CreateBot,
ListBots,
ListAllBots,
RunBot,
Cancel,
Greet,
None
};
public Dictionary<Intent, IntentScore> Intents;
public class _Entities
{
public string Name;
}
public _Entities Entities;
[JsonExtensionData(ReadData = true, WriteData = true)]
public IDictionary<string, object> Properties { get; set; }
public void Convert(dynamic result)
{
var _result = JsonConvert.DeserializeObject<ChatbotIntent>(JsonConvert.SerializeObject(result, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }));
Text = _result.Text;
AlteredText = _result.AlteredText;
Intents = _result.Intents;
Entities = _result.Entities;
Properties = _result.Properties;
}
public (Intent intent, double score) TopIntent()
{
Intent maxIntent = Intent.None;
var max = 0.0;
foreach (var entry in Intents)
{
if (entry.Value.Score > max)
{
maxIntent = entry.Key;
max = entry.Value.Score.Value;
}
}
return (maxIntent, max);
}
}
}
In the previous snippet, the important part is the _Entities class which define how the entities look from coming back from Luis. Since I only have 1 simple string entity "Name", I thought this is sufficient.
public class _Entities
{
public string Name;
}
However when I run it and I give it an utterance like:
"list bots mybots"
Luis would correctly assign Name="mybots" and get the correct intent, but it crash on the JsonConvert.DeserializeObject line saying the json format is incorrect. I assume this is complaining about the class I made? And not the actual JSON result from luis?
What do I need to add to the _Entities class so the luis entity can be successfully deserialzied?

I know this is an old question but I'm facing the same situation now so I want to contribute with the step-by-step that worked for me.
As #ranusharao and Bill said, you need to download LUISGen from GitHub.
Start a CMD, go to your solution's directory
cd C:\MySolutionFolder
and run
luis init
if you haven't done yet.
It will ask you for your App ID and information that you get in luis.ai.
After that, go to luis.ai / Manage / Versions, click on your current version and click Export as Json.
Place your JSON file in your solution's folder.
Once you have done that, run the following command in your console:
LUISGen C:\MyJSONPath\MyBot.json -cs MyClassName -o C:\MySolutionFolder
That -cs stands for C#, but if you are usign Typescript then change it for "-ts".
So there you have it, you can access your class with something like:
var result = await _luisRecognizerService._recognizer.RecognizeAsync<MyClassName>(turnContext, cancellationToken);
Console.WriteLine(result.Entities.Producto);
_luisRecognizerService is my instance of LuisRecognizer (dependency injection)

As recommended by #ranusharao, using LUISGen tool, a class will automatically be generated that works with the bot framework.

Related

ASP.NET API returning strange values to Angular

I appear to be having some issues with my ASP.NET API talking to Angular and I'm not totally sure why. I'm hoping someone can glance at what I've done and look for anything obvious.
In my API Controller I have the following code:
// Data Structure to hold results from query
public class MyContainer
{
public ulong id;
public int num;
public MyContainer(ulong id, int num)
{
this.id = id;
this.num = num;
}
}
public class MyAPIController : ControllerBase {
[Route("/Testing")]
[AllowAnonymous]
[HttpGet]
public IEnumerable<MyContainer> GetMethod()
{
var x = from r in context.TableOne
group r by r.Id into g
select new MyContainer(g.Key, g.Count() );
var y = x.First();
logger.LogInformation(y.num.ToString()); // This outputs correctly!
return x.ToList();
}
}
And in Angular, I have the following service:
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
class MyContainer {
public id: number;
public num: number;
}
export class MyService {
...
getMethod(): Observable<MyContainer> {
let url = this.baseUrl + 'Testing';
let test = this.http.get(url, httpOptions);
// This outputs an array with the correct number of elements, but they are all blank...
// Such as [{…}, {…}, {…}], and when expanded, they are empty.
test.subscribe(x => console.log(x));
return test;
}
}
Please note, I've added three comments in my code above to help highlight my issues.
I've just started learning ASP.NET so I imagine I'm missing something obvious.
What I know works:
The Routing works -- I am able to hit my API's GetMethod() without any problems.
My LINQ Database Query -- As mentioned in the second comment, from my Logger in the API Controller I see my API Function successfully queries the database and returns the value I'm expecting. It just doesn't get passed to Angular correctly.
What I've Tried:
Adding the [ApiController] attribute to my API Controller.
This actually gives me a weird 400 error, "The input does not contain does not contain any JSON tokens..."?
Using a POST instead of a GET.
Modifying the data structures used in the return (i.e. trying List<MyContainer>)
Using raw SQL instead of LINQ.
Changing MyContainer to use only strings + converting the results in the database query to strings (to see if it could be a serialization issue).
What I think the Problems Could Be:
ASP.NET/Angular don't like me returning data via my MyContainer class.
Since I am using the Entity Core framework, it may not like that MyContainer is not registered as a "Keyless Entity Type", but it is not giving me any errors so I don't think this is the problem.
Every single time I go to test this API function, God sends down cosmic rays in just the right way to hit the electrons storing the API's return result in Angular's memory, thus giving me the correct number of blank elements.
Any help is immensely appreciated! I have a feeling it has to do with me using a custom data type, but again, I don't have any idea why that would be an issue unless its unable to be converted to JSON...
Edit: Using the following libraries
using System;
using System.Data.SqlClient;
using System.Linq;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
The problem is that your DTO (MyContainer) is not serializing its fields. IIRC, by default, most JSON serializers for .NET only serialize public properties, not public fields.
I assume you're using Newtonsoft.Json, but it's trivial to convert this to System.Text.Json:
The main fix is to change your MyContainer DTO to use properties instead of fields. Note that using JsonProperty is optional, but I prefer setting explicit names (and don't use camelCase for public instance members in .NET, only use TitleCase):
public class MyContainer
{
public MyContainer(ulong id, int number)
{
this.Id = id;
this.Number = num;
}
[JsonProperty( "id" )]
public UInt64 Id { get; }
[JsonProperty( "num" )]
public Int32 Number { get; }
}
Secondarily, I'd improve your controller action like so, but please read these articles:
https://learn.microsoft.com/en-us/aspnet/core/web-api/advanced/conventions?view=aspnetcore-3.1
https://learn.microsoft.com/en-us/aspnet/core/web-api/action-return-types?view=aspnetcore-3.1
[ApiController]
public class MyApiController : ControllerBase
{
[Route("/Testing")] // <-- This implicitly allows GET and HEAD, you don't need a separate [HttpGet] attribute.
[AllowAnonymous]
[ProducesResponseType(StatusCodes.Status200OK, typeof(List<MyContainer>))]
public async Task<IActionResult> GetMethod()
{
// Do data access asynchronously...
var groups = await this.context
.TableOne
.GroupBy( r => r.Id )
.Select( grp => new { Id = grp.Key, Count = grp.Count() } )
.ToListAsync();
// ...but transform the data synchronously:
List<MyContainer> list = groups
.Select( g => new MyContainer( g.Id, g.Count ) )
.ToList();
return this.OK( list );
}
}
In your TypeScript code, it's generally a better idea to use readonly interfaces rather than classes to represent DTOs because you can meaningfully cast deserialized JSON (and object-literals in general) to interfaces, but not meaningfully cast object-literals to classes (as JSON objects don't have function-properties or inheritance anyway):
So change this:
class MyContainer {
public id: number;
public num: number;
}
To this:
interface MyContainer {
readonly id : number;
readonly num: number;
}

Returning a List or IEnumerable with IHttpActionResult [duplicate]

I am working with ASP.NET MVC 5 Web Api. I want consult all my users.
I wrote api/users and I receive this:
"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'"
In WebApiConfig, already I added these lines:
HttpConfiguration config = new HttpConfiguration();
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
But it still doesn't work.
My function for return data is this:
public IEnumerable<User> GetAll()
{
using (Database db = new Database())
{
return db.Users.ToList();
}
}
If you are working with EF, besides adding the code below on Global.asax
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings
.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters
.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
Dont`t forget to import
using System.Data.Entity;
Then you can return your own EF Models
Simple as that!
When it comes to returning data back to the consumer from Web Api (or any other web service for that matter), I highly recommend not passing back entities that come from a database. It is much more reliable and maintainable to use Models in which you have control of what the data looks like and not the database. That way you don't have to mess around with the formatters so much in the WebApiConfig. You can just create a UserModel that has child Models as properties and get rid of the reference loops in the return objects. That makes the serializer much happier.
Also, it isn't necessary to remove formatters or supported media types typically if you are just specifying the "Accepts" header in the request. Playing around with that stuff can sometimes make things more confusing.
Example:
public class UserModel {
public string Name {get;set;}
public string Age {get;set;}
// Other properties here that do not reference another UserModel class.
}
Given right answer is one way to go, however it is an overkill when you can fix it by one config settings.
Better to use it in the dbcontext constructor
public DbContext() // dbcontext constructor
: base("name=ConnectionStringNameFromWebConfig")
{
this.Configuration.LazyLoadingEnabled = false;
this.Configuration.ProxyCreationEnabled = false;
}
Asp.Net Web API Error: The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'
Add this code to global.asax below on Application_Start:
Update from .Ignore to .Serialize . It must work.
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
public class UserController : ApiController
{
Database db = new Database();
// construction
public UserController()
{
// Add the following code
// problem will be solved
db.Configuration.ProxyCreationEnabled = false;
}
public IEnumerable<User> GetAll()
{
return db.Users.ToList();
}
}
I resolved it using this code to WebApiConfig.cs file
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
I don't like this code:
foreach(var user in db.Users)
As an alternative, one might do something like this, which worked for me:
var listOfUsers = db.Users.Select(r => new UserModel
{
userModel.FirstName = r.FirstName;
userModel.LastName = r.LastName;
});
return listOfUsers.ToList();
However, I ended up using Lucas Roselli's solution.
Update: Simplified by returning an anonymous object:
var listOfUsers = db.Users.Select(r => new
{
FirstName = r.FirstName;
LastName = r.LastName;
});
return listOfUsers.ToList();
Adding this in your Application_Start() method of Global.asax file should solve the problem
protected void Application_Start()
{
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings
.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters
.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
// ...
}
METHOD 2: [Not recommended]
If you are working with EntityFramework, you can disable proxy in your DbContext class constructor. NOTE: this code wll be removed if you update the model
public class MyDbContext : DbContext
{
public MyDbContext()
{
this.Configuration.ProxyCreationEnabled = false;
}
}
There's also this scenario that generate same error:
In case of the return being a List<dynamic> to web api method
Example:
public HttpResponseMessage Get()
{
var item = new List<dynamic> { new TestClass { Name = "Ale", Age = 30 } };
return Request.CreateResponse(HttpStatusCode.OK, item);
}
public class TestClass
{
public string Name { get; set; }
public int Age { get; set; }
}
So, for this scenario use the [KnownTypeAttribute] in the return class (all of them) like this:
[KnownTypeAttribute(typeof(TestClass))]
public class TestClass
{
public string Name { get; set; }
public int Age { get; set; }
}
This works for me!
My personal favorite: Just add the code below to App_Start/WebApiConfig.cs. This will return json instead of XML by default and also prevent the error you had. No need to edit Global.asax to remove XmlFormatter etc.
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
Just put following lines in global.asax:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
Import
using System.Data.Entity;
Use AutoMapper...
public IEnumerable<User> GetAll()
{
using (Database db = new Database())
{
var users = AutoMapper.Mapper.DynamicMap<List<User>>(db.Users);
return users;
}
}
Use the following namespace:
using System.Web.OData;
Instead of :
using System.Web.Http.OData;
It worked for me
Add the below line
this.Configuration.ProxyCreationEnabled = false;
Two way to use ProxyCreationEnabled as false.
Add it inside of DBContext Constructor
public ProductEntities() : base("name=ProductEntities")
{
this.Configuration.ProxyCreationEnabled = false;
}
OR
Add the line inside of Get method
public IEnumerable<Brand_Details> Get()
{
using (ProductEntities obj = new ProductEntities())
{
this.Configuration.ProxyCreationEnabled = false;
return obj.Brand_Details.ToList();
}
}
Use [Serializable] for class:
Example:
[Serializable]
public class UserModel {
public string Name {get;set;}
public string Age {get;set;}
}
It worked for me!
Solution that worked for me:
Use [DataContract] for class and [DataMember] attributes for each property to serialize. This is enough to get Json result (for ex. from fiddler).
To get xml serialization write in Global.asax this code:
var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
xml.UseXmlSerializer = true;
Read this article, it helped me to understand serialization:
https://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization
To add to jensendp's answer:
I would pass the entity to a user created model and use the values from that entity to set the values in your newly created model. For example:
public class UserInformation {
public string Name { get; set; }
public int Age { get; set; }
public UserInformation(UserEntity user) {
this.Name = user.name;
this.Age = user.age;
}
}
Then change your return type to: IEnumerable<UserInformation>
While all these answers above are correct, one may want to check the InnerException > ExceptionMessage.
If it says something like this "The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.". This could be an issue because of default behavior of the EF.
By assigning LazyLoadingEnabled = false in your DbContext constructor will do the trick.
public class MyDbContext : DbContext
{
public MyDbContext()
{
this.Configuration.LazyLoadingEnabled = false;
}
}
For more detailed reading about EagerLoading and LazyLoading behavior of EF refer this MSDN Article.
In my case I have had similar error message:
The 'ObjectContent`1' type failed to serialize the response body for
content type 'application/xml; charset=utf-8'.
But when I dig deeper in it, the issue was:
Type 'name.SomeSubRootType'
with data contract name
'SomeSubRootType://schemas.datacontract.org/2004/07/WhatEverService'
is not expected. Consider using a DataContractResolver if you are
using DataContractSerializer or add any types not known statically to
the list of known types - for example, by using the KnownTypeAttribute
attribute or by adding them to the list of known types passed to the
serializer.
The way I solved by adding KnownType.
[KnownType(typeof(SomeSubRootType))]
public partial class SomeRootStructureType
This was solved inspired from this answer.
Reference: https://msdn.microsoft.com/en-us/library/ms730167(v=vs.100).aspx
I basically add one line which they are
entities.Configuration.ProxyCreationEnabled = false;
to UsersController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using UserDataAccess;
namespace SBPMS.Controllers
{
public class UsersController : ApiController
{
public IEnumerable<User> Get() {
using (SBPMSystemEntities entities = new SBPMSystemEntities()) {
entities.Configuration.ProxyCreationEnabled = false;
return entities.Users.ToList();
}
}
public User Get(int id) {
using (SBPMSystemEntities entities = new SBPMSystemEntities()) {
entities.Configuration.ProxyCreationEnabled = false;
return entities.Users.FirstOrDefault(e => e.user_ID == id);
}
}
}
}
You will have to define Serializer Formatter within WebApiConfig.cs available in App_Start Folder like
Adding config.Formatters.Remove(config.Formatters.XmlFormatter);
// which will provide you data in JSON Format
Adding config.Formatters.Remove(config.Formatters.JsonFormatter);
// which will provide you data in XML Format
Another case where I received this error was when my database query returned a null value but my user/view model type was set as non-nullable. For example, changing my UserModel field from int to int? resolved.
This also happens when the Response-Type is not public!
I returned an internal class as I used Visual Studio to generate me the type.
internal class --> public class
Visual Studio 2017 or 2019 is totally unthoughtful on this, because Visual Studio itself requires the output to be in json format, while Visual Studio's default format is "XmlFormat" (config.Formatters.XmlFormatter).
Visual Studio should do this automatically instead of giving developers so much trouble.
To correct this problem, go to the WebApiConfig.cs file, and add
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
after "config.MapHttpAttributeRoutes();" in the Register(HttpConfiguration config) method. This would allow your project to produce json output.
In my case I solved recreating the database.
I made some changes in a model and launching Update-Database in Package Manager Console I got the following Error:
"The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_dbo.Activities_dbo.Projects_ProjectId". The conflict occurred in database "TrackEmAllContext-20190530144302", table "dbo.Projects", column 'Id'."
In case: If adding code to WebApiConfig.cs or Global.asax.cs doesn't work for you:
.ToList();
Add .ToList() function.
I tried out every solution but following worked for me:
var allShops = context.shops.Where(s => s.city_id == id)**.ToList()**;
return allShops;
I hope, it helps.
in my case, it was fixed when I removed the virtual keyword before my navigation properties,
I mean the reference tables.
so I changed
public virtual MembershipType MembershipType { get; set; }
to:
public MembershipType MembershipType { get; set; }

Pass parameters to AWS Lambda function

I have a Lambda function and it supposes to take 3 parameters
public async Task<string> FunctionHandler(string pName, string dictName, ILambdaContext context)
{
//code...
}
I am using Visual Studio 2015, I published this to AWS environment, what do I put in the sample input box to invoke this function?
Personally, I've not experimented with async Task in the Lambda entry point so not able to comment on that.
However, another way to go about it is to change the Lambda function entry point to:
public async Task<string> FunctionHandler(JObject input, ILambdaContext context)
Then pull the two variables out of that like so:
string dictName = input["dictName"].ToString();
string pName = input["pName"].ToString();
Then in the AWS Web Console you enter:
{
"dictName":"hello",
"pName":"kitty"
}
Or instead one could take the JObject value and use it as shown in the following example code:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
namespace SimpleJsonTest
{
[TestClass]
public class JsonObjectTests
{
[TestMethod]
public void ForgiveThisRunOnJsonTestJustShakeYourHeadSayUgghhhAndMoveOn()
{
//Need better names than dictName and pName. Kept it as it is a good approximation of software potty talk.
string json = "{\"dictName\":\"hello\",\"pName\":\"kitty\"}";
JObject jsonObject = JObject.Parse(json);
//Example Zero
string dictName = jsonObject["dictName"].ToString();
string pName = jsonObject["pName"].ToString();
Assert.AreEqual("hello", dictName);
Assert.AreEqual("kitty", pName);
//Example One
MeaningfulName exampleOne = jsonObject.ToObject<MeaningfulName>();
Assert.AreEqual("hello", exampleOne.DictName);
Assert.AreEqual("kitty", exampleOne.PName);
//Example Two (or could just pass in json from above)
MeaningfulName exampleTwo = JsonConvert.DeserializeObject<MeaningfulName>(jsonObject.ToString());
Assert.AreEqual("hello", exampleTwo.DictName);
Assert.AreEqual("kitty", exampleTwo.PName);
}
}
public class MeaningfulName
{
public string PName { get; set; }
[JsonProperty("dictName")] //Change this to suit your needs, or leave it off
public string DictName { get; set; }
}
}
The point is I don't know if you can have two input variables in an AWS Lambda. Odds are you can't. Besides it's probably best if you stick with a json string or object to pass in the multiple variables one needs.

How can I configure Automapper 4 to allow a null destination value

I'm having some problems working out how to get Automapper 4.2.1 to allow for a type mapping where the destination value might be null depending on the source value.
Older versions of Automapper allowed an AllowNullDestination flag to be set via the Mapper configuration but I can't find the equivalent recipe for the new version and the old mechanism of configuring via the static Mapper object seems to have been obsoleted.
I have tried the following without success:
Mapper.Configuration.AllowNullDestinationValues = true;
Mapper.AllowNullDestinationValues = true;
Mapper.Initialize(c=>c.AllowNullDestinationValues=true);
Here's a simple test case demonstrating the problem. This fails on the final line with an AutoMapperMappingException since the Substitute method is returning null. I would like both mappings to succeed.
I would prefer to avoid the use of .ForMember in the solution since in the real scenario I'm trying to address, the mapping between bool and 'object' (actually a custom class) should apply across the entire object tree.
Although there are several similar questions here on StackOverflow, I haven't found one that refers to a recent version of Automapper.
Thanks in advance for any suggestions
using AutoMapper;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace AutoMapperTest
{
[TestClass]
public class ExampleTest
{
[TestMethod]
public void NullDestinationCanBeMapped()
{
var mapper = new MapperConfiguration(configuration =>
{
configuration.CreateMap<Source, Target>();
//How should the following mapping be modified to pass the test?
configuration.CreateMap<bool, object>()
.Substitute(i => i ? null : new object());
}).CreateMapper();
var target1 = mapper.Map<Source, Target>(new Source {Member = false}); //succeeds
Assert.IsNotNull(target1.Member); //pass
var target2 = mapper.Map<Source, Target>(new Source {Member = true}); //fails to map with exception
Assert.IsNull(target2.Member); //not reached
}
}
public class Source
{
public bool Member { get; set; }
}
public class Target
{
public object Member { get; set; }
}
}
Instead of using Substitute, use ConvertUsing...
configuration.CreateMap<bool, MyClass>()
.ConvertUsing(i => i ? null : new object());

Using ASP.Net MVC Data Annotation outside of MVC

i was wondering if there is a way to use ASP.Net's Data annotation without the MVC site.
My example is that i have a class that once created needs to be validated, or will throw an error. I like the data annotations method, instead of a bunch of if blocks fired by the initaliser.
Is there a way to get this to work?
I thought it would be something like:
Add data annotations
Fire a method in the initialiser that calls the MVC validator on the class
any ideas? i must admit i havent added the MVC framework to my project as i was hoping i could just use the data annotations class System.ComponentModel.DataValidation
Here's an example:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
public class Foo
{
[Required(ErrorMessage = "the Bar is absolutely required :-)")]
public string Bar { get; set; }
}
class Program
{
public static void Main()
{
var foo = new Foo();
var results = new List<ValidationResult>();
var context = new ValidationContext(foo, null, null);
if (!Validator.TryValidateObject(foo, context, results))
{
foreach (var error in results)
{
Console.WriteLine(error.ErrorMessage);
}
}
}
}
But quite honestly FluentValidation is much more powerful.

Categories