Model DataAnnotation for asp.net mvc - javascript

Is there any way to get dataanotations for my models directly from my database?
I have a database with lot's of data and tables, so i am generating my model with entity framework from database, so i get classes, but i want to know can entity framework or some other orm get properities and constrains directly from database and put them in classes as data anotation like [required] or [datatype(datatype.emailadress)]

Yes. You can inherit the ModelMetadataProvider class:
public class LocalizedModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType,
Func<object> modelAccessor, Type modelType, string propertyName)
{
var metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
if (containerType == null || propertyName == null)
return metadata;
// Load all metadata from your database here.
return metadata;
}
}
I'm creating a project called Griffin.MvcContrib which is almost done and has a administration area where you can handle all localization (zero-code) for both models and validation messages.
By using it you can just implement the following interface to get support for your database:
// the actual code file has detailed explanations of each method.
public interface ILocalizedStringProvider
{
string GetModelString(Type model, string propertyName);
string GetModelString(Type model, string propertyName, string metadataName);
string GetValidationString(Type attributeType);
string GetEnumString(Type enumType, string name);
}
Update
Where is not important. And you do not have to use DataAnnotation attributes on your models (the [Display] attribute). I just inherit the DataAnnotationsModelMetadataProvider to be able to use the attributes.
Create the class anywhere.
Read from the database
Configure MVC to use it in global.asax
Example:
ModelMetadataProviders.Current = new YourModelMetadataProvider();

Related

Serialize form to string and deserealize it later to complex view model

I'm implementing the "Save Draft" functionality on my dynamically generated page and trying to make it as generic as possible. All my controllers and pages should support it and that's why I thought about creating a SaveDraft() POST action in my base controller which will receive a serialized form as a string which can be directly saved into the database and deserialized to a view model later in the specific get action using specific view model
[HttpPost]
public ActionResult SaveDraft(string jsonData, long id)
My first idea was to create the generic base controller and pass the view model type to it but the problem is that some controllers have multiple differently named POST actions and using different view model types, I cant change it now.
Some view models are complex and looking like
public class CollateralsDataModel
{
//...
public List<Applicant> Applicants { get; set; }
}
public class Applicant
{
public long ApplicantId { get; set; }
public IList<RealEstateSecurityCollateralsDTO> RealEstateSecurityCollaterals { get; set; }
public IList<AdditionalCollateralDTO> AdditionalCollaterals { get; set; }
}
public class RealEstateSecurityCollateralsDTO
{
[Required]
[Display(ResourceType = typeof(CollateralsData), Name = nameof(CollateralsData.RealEstateSecurityType))]
public int? RealEstateSecurityTypeId { get; set; }
//...
}
The input names on the form are looking like
"Applicants[0].MortgageApplicantId": "11595",
"Applicants[0].RealEstateSecurityCollaterals[0].Id": "17",
"Applicants[1].MortgageApplicantId": "11596",
"Applicants[1].RealEstateSecurityCollaterals.Index": "0",
"Applicants[1].AdditionalCollaterals[0].Id": "138",
"Applicants[1].AdditionalCollaterals[0].AdditionalCollateralTypeId": "4",
My question is - how can I serialize them to the string so I can deserialize it later?
I tried using different combinations of
$('.draft-data-form').serializeArray()
$('.draft-data-form').serialize()
JSON.stringify($('.draft-data-form').serializeArray());
but in my Action I get the flat JSON structure and I can't deserialize it
var obj = JsonConvert.DeserializeObject<CollateralsDataModel>(jsonData);
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type '...CollateralsDataModel' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
I've also tried to deserialize it as a list but then I get the List of 115 entries
var obj = JsonConvert.DeserializeObject<List<CollateralsDataModel>>(jsonData);
So my question is - how can I serialize them to the string so I can deserialize it later?
You do not want to serialize/deserialize a List. Only a single instance of the model.
I would guess that the error is in instantiating the list within the model. I know that the DataContractSerializer has an issue where if the List is not instantiated to an empty list when the model is constructed then the deserialization is unable to add to it.
Not sure if this is the same problem you are facing but could be worth a try.
eg. use:
public List<Applicant> Applicants { get; set; } = new List<Applicant>();

Error using dynamic keyword in asp.net mvc 4

I am getting this long error when i accpet the parameter as dynamic on my server side action method in mvc 4.
{"Message":"An error has
occurred.","ExceptionMessage":"'Newtonsoft.Json.Linq.JObject' does not
contain a definition for
'TournamentId'","ExceptionType":"Microsoft.CSharp.RuntimeBinder.RuntimeBinderException","StackTrace":"
at CallSite.Target(Closure , CallSite , Object )\r\n at
System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite
site, T0 arg0)\r\n at
ManagerDeTorneos.Web.Controllers.TournamentDateController.Create(Object
data) in
F:\Prince\Projects\Juan\trunk\ManagerDeTorneos.Web\Controllers\TournamentDateController.cs:line
133\r\n at lambda_method(Closure , Object , Object[] )\r\n at
System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c_DisplayClass13.b_c(Object
instance, Object[] methodParameters)\r\n at
System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object
instance, Object[] arguments)\r\n at
System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1
func, CancellationToken cancellationToken)"}
[HttpPost]
public HttpResponseMessage AddMatch(dynamic data)
{
int tournamentDateId = (int)data.TournamentDateId.Value;
var tournamentDate = Catalog.TournamentDateRepository.GetById(tournamentDateId);
if (tournamentDate == null)
{
throw ExceptionHelper.NotFound("Fecha no encontrada!");
}
In The above method data Contains tournamentId as sent from ajax call as JSON.Stringify({'TournamentId':'5'}).
Can anybody tell me what is the cause of error. I even replaced the dll of Newtonsoft.Json as well
You are right dan but i fixed my issue by removing that dll from GAC. May be in GAC it was using old assembly
The error is caused by the fact that you typed your parameter as dynamic, which means that the model binder doesn't know what to make it. It's the same as if you were to declare it as an object. Since you are providing JSON, it serializes the object as a Json.Net JObject. Just because you define it as a dynamic doesn't mean that it's going to magically take whatever shape you need it to.
Change it to a concrete type - something that matches the structure of the provided JSON:
public class TournamentInfo
{
public int TournamentId { get; set; }
}
[HttpPost]
public HttpResponseMessage AddMatch(TournamentInfo data)
{
int tournamentDateId = data.TournamentId;
var tournamentDate = Catalog.TournamentDateRepository.GetById(tournamentDateId);
if (tournamentDate == null)
{
throw ExceptionHelper.NotFound("Fecha no encontrada!");
}
This way, the binder knows what it's supposed to turn the JSON into, and since TournamentInfo matches the structure of the JSON, it won't have any trouble serializing it.
Don't misuse dynamic. It was not introduced into C# so developers could stop defining classes.

Assign new values in a Breeze entity

I'm developing a spa web application with BreezeJS and the DurandalJS Framework. I came accross a problem which I can't fix.
I have a entity called: Car, this entity contains name, number, owner, type en manufacturer. In this entity the name and number are filled in as the entity is created AND saved in the database. The other properties are allowed to be NULL.
This because the other values are filled in during a modal/ dialog screen. Here a user can select a owner from a list and also a type and manufacturer from a list. When the user selects one from a dropdown the selected value should be assigned to the value of the Car entity. How can I get this to work?
Car().Owner = newOwner;
Car.Owner() = newOwner;
This won't work. I tried a lot of combinations. Remember that the value was null first and that I can't insert a new value;S
Edit 1
Here the Entity Framework model of Car
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Estimate_App.Models
{
public class tblCar
{
[Key]
public int CarID { get; set; }
public string CarNumber { get; set; }
private DateTime _CreationDate;
public DateTime CreationDate
{
get { return this._CreationDate; }
set { this._CreationDate = DateTime.Now; }
}
//This is the Owner
[ForeignKey("Owner")]
public int? OwnerID { get; set; }
public tblOwner Owner { get; set; }
}
}
Here is what I put in my Car().Owner(), consider Container should be Car (this is an other project with the same problem)
I hover my mouse over newValue.
Edit 2
By a answer of Julián Yuste I also tried this but it didn't work. Here is the error:
When I do Container().Owner(newValue);
Edit 3
The code that fetches the owners
breeze.EntityQuery.from("Customers")
.using(dataservice.manager)
.execute().then(function (data) {
data.results.forEach(function (item) {
tempCustomerList.push(item); //ko.observableArray([]);
});
}).fail(function (data) {
});
Are you using the EntityManager from your dataservice object in order to create the newOwner object?
In other words, you probably shouldn't be doing this*:
var newOwner = new Owner();
newOwner.OwnerID = 123;
You should do this:
var newOwner = dataservice.manager.createEntity('Owner', { OwnerID: 123 });
*Note that can actually use new Owner(), but that requires you to define entity constructors in your code. :-)
For more information, check out the Breeze documentation: http://www.breezejs.com/documentation/creating-entities
Also, note that you can read the Breeze JavaScript code to help you understand the issue. If you search breeze.debug.js for your error message (An Entity cannot be attached to an entity in another EntityManager. One of the two entities must be detached first.), you will find the line of code that is causing the exception. It may be helpful to backtrack from there.
Edit
The answer to the question was to make sure that the EntityManager object is a Singleton (in this case, the dataservices.manager object).
In other words, use the same EntityManager object to update objects as you use to query for objects.
I think we need more information. Is the 'Owner' property an instance of another entity or is it a primitive type, i.e. string, number etc?
If it is an entity then I would first check that your 'newOwner' variable was also in fact an entity.
If owner is an observable, you need to asign the new value as: owner(newOwner).
Greetings.

How to pass a List to javascript in JSF

I am struggling with a JSF project.
In my service, I retrieve a List of custom object (here Sales), and I have to pass it to my jsf view, specifically into the javascript, to make graphs.
My problem is, I don't understand how to send the data from the controller (my managed beans) to my view, and which tag to use in my view to retrieve it in my javascript.
I think I can pass my data like this, but I'm not sure
public String passData() {
List<Sales> bestSelling = saleService.getBestSellingProduct(null, null, null, null);
List<Sales> worstSelling = saleService.getWorstSellingProduct(null, null, null, null);
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("bestSelling", bestSelling);
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("worstSelling", worstSelling);
return "./all.jsf?faces-redirect=true";
}
You need to create a JSON object that you'll assign to a JavaScript variable. To create JSON you may find useful to incorporate a library like Gson.
So, it'll look like:
var sales = #{bean.jsonList};
with Bean#getJsonList as:
public String getJsonList() {
return (sales == null) ? "" : new Gson.toJson(sales);
}
Just don't forget that the script with such assignment must be handled by the FacesServlet.

JSON representation of a list of keyvaluepairs

I have an MVC JSON controller method that I call from frontend. It looks like this:
public JsonResult FacetedSearch(string searchString, List<KeyValuePair<string,string>> facets)
I'm calling it via jQuery ajax at the frontend, I'm serializing the data in the following manner:
JSON.stringify({searchString: "the matrix", facets: [{Key: "TypeName", Value: "Feature Film"}, {Key:"TypeName", Value:"Series"}]}
When I debug through my application code, I see that searchString gets passed successfully over to the MVC method, but the variable facets gives me a list of 2 KeyValuePairs with null Key and Value.
I've looked at my serialization and it seems valid but for whatever reason it isn't going over to my application correctly. What gives?
Rather than expect two objects in your signature, it would make more sense to expect a single object that contains both of your parameters. This would be something like the following.
public JsonResult FacetedSearch(RequestObject requestObject)
{ }
public class RequestObject
{
public string searchString { get; set; }
public List<KeyValuePair<string,string>> facets { get; set; }
}
This way, when you send your JSON object, the signature is an object with two properties, just like the object that you are sending.
Per Is there a serializable generic Key/Value pair class in .NET?
I found out why it's not serializing it. Apparently it's unserializable.

Categories

Resources