Good day everyone,
I have a doubt on my currently development, the thing is i've created a project using ntier and data application block for my data access layer so, i have a package named Entities where i create all my classes and i was trying to use error messages mapped to a resource file the problem is when i write the following code it marks up with error:
(Entity-Base-Clients)
public partial class Clients {
public Int32 Id {get;set;}
[Display(Name="Name",
ResourceType=typeof(Resources.Language))]
[Required(AllowEmptyStrings=false,
ErrorMessageResourceName="Id",
ErrorMessageResourceType=typeof(Resources.Language))]
public string Name {get;set;}
}
In the following code it marks up error in "Resources" (which is the folder where i put my resource files) and "Language" is the resource file.
But when i do the exactly the same thing on the "Model" folder didn't marks up any error
(Model-Clients)
public Int32 Id {get;set;}
[Display(Name="Name",
ResourceType=typeof(Resources.Language))]
[Required(AllowEmptyStrings=false,
ErrorMessageResourceName="Id",
ErrorMessageResourceType=typeof(Resources.Language))]
public string Name {get;set;}
}
Do i have doing something wrong? am i missing a reference or configuration of the RF?
Thanks in advance
[Display(Name = "Name"), Required(ErrorMessageResourceType = typeof(Resources.Resources), ErrorMessageResourceName ="nameHasToBeGiven")]
public string name { get; set; }
this one is way easier
This is an old problem. To solve it I deactivated the EDMX Code generation and I created external TT files to generate :
DomainLayer : Contains EF EDMX classes (with navigation)
DataLayer : Contains stuff to query data
[Serializable]
public partial class Contact : _DomainLayer_Base
{
#region Primitive Properties
/// <summary>
/// Gets or sets Id.
/// </summary>
/// <value>The Id.</value>
public virtual int Id
{
get;
set;
}
/// <summary>
/// Gets or sets FK_Language.
/// </summary>
/// <value>The FK_Language.</value>
/// <remarks>
/// Foregn key of Contact
///
/// </remarks>
public virtual int FK_Language
{
get { return _fK_Language; }
set
{
try
{
_settingFK = true;
if (_fK_Language != value)
{
if (Language != null && Language.Id != value)
{
Language = null;
}
_fK_Language = value;
}
}
finally
{
_settingFK = false;
}
}
}
}
MetaDataLayer : Contains EF Independant classes with data annotations linked to resources (without navigation)
[Serializable]
public partial class Contact_MetaData : _MetaDataLayer_Base
{
[Display(Name = "Ety_Contact_Id" , ResourceType = typeof(InnovaApp.Layers.ResourcesLayer.Properties.MetaDataResources))]
[Required(ErrorMessageResourceName = "ErrMsgRequired",ErrorMessageResourceType = typeof(InnovaApp.Layers.ResourcesLayer.Properties.Resources))]
public virtual int Id
{
get;
set;
}
[Display(Name = "Ety_Contact_FK_Language" , ResourceType = typeof(InnovaApp.Layers.ResourcesLayer.Properties.MetaDataResources))]
[Required(ErrorMessageResourceName = "ErrMsgRequired",ErrorMessageResourceType = typeof(InnovaApp.Layers.ResourcesLayer.Properties.Resources))]
public virtual int FK_Language
{
get;
set;
}
MetaModels : Inside the portal, MetaModels are MetaData members containers. They contains data required by portal. Example :If you have a foreign key, the ForeignKey value will be in the MetaData but ListItems used to fill the lookup will be in the MetaModel.
EntityLayer : Contains EF EDMX
When I create a EF Query I prefix result with db :
When I use the data in the view, I use my MetaDataLayer :
public class ContactViewer_MetaModel : Contact_MetaData
To transfert data from DomainLayer to MetaDataLayer I Use Emit Mapper because My TT files guaranty same signature between Domain and MetaData.
toReturn = ObjectMapperManager.DefaultInstance.GetMapper<Contact, ContactViewer_MetaModel>().Map(dbContact);
and in the view :
#model InnovaApp.Layers.SecurityLayer.Models.MetaModels.Contact_MetaModel
#Html.HiddenFor(m => m.Id)
<ol class="olMainForm">
<li>
#Html.LabelFor(m => m.FK_Genre)
#Html.DropDownListFor(m => m.FK_Genre, Model.Genres)
#Html.ValidationMessageFor(m => m.FK_Genre)
</li>
</ol>
You can find the full source here :
https://myprettycms.codeplex.com
Related
Recently i've start playing with new web api help page functionality, that was recently added to web api project template. And i have a notice that some "Additional information" column is always 'none'.
After some looking at markup i found that this info should arrive from attributes
<td class="parameter-annotations">
#if (parameter.Annotations.Count > 0)
{
foreach (var annotation in parameter.Annotations)
{
<p>#annotation.Documentation</p>
}
}
else
{
<p>None.</p>
}
</td>
But what kind of attribute i should use, to populate additional information?
Thanks
See this site for an example of how to add additional information.
It's basically annotating your model, so in your case it would be something like:-
public class Product
{
/// <summary>
/// The id of the product
/// </summary>
[Required]
public int Id { get; set; }
/// <summary>
/// The name of the product
/// </summary>
[MaxLength(50)]
public string Name { get; set; }
}
Which would give you an output like this:-
I am looking to place attributes on my WCF data contract members to validate string length and possibly use regex for more granular parameter validation.
I can the [Range] attribute for numeric and DateTime values and was wondering if any of you have found any other WCF Data Member attributes I can use for data validation. I have found a bevvy of attributes for Silverlight but not for WCF.
Add System.ComponentModel.DataAnnotations reference to your project.
The reference provides some DataAnnotations which are:
RequiredAttribute, RangeAttribute, StringLengthAttribute, RegularExpressionAttribute
you can in your datacontract like below.
[DataMember]
[StringLength(100, MinimumLength= 10, ErrorMessage="String length should be between 10 and 100." )]
[StringLength(50)] // Another way... String max length 50
public string FirstName { get; set; }
[DataMember]
[Range(2, 100)]
public int Age { get; set; }
[DataMember]
[Required]
[RegularExpression(#"\b[A-Z0-9._%-]+#[A-Z0-9.-]+\.[A-Z]{2,4}\b", ErrorMessage = "Invalid Mail id")]
public string Email { get; set; }
Hope this helps.
Manually Validating Values: You can manually apply the validation test by using the Validator class. You can call the ValidateProperty method on the set accessor of a property to check the value against the validation attributes for the property. You must also set both ValidatesOnExceptions and NotifyOnValidationError properties to true when data binding to receive validation exceptions from validation attributes.
var unsafeContact = Request["contactJSON"];
try
{
var serializer = new DataContractJsonSerializer(typeof(Contact));
var stream = new MemoryStream(Encoding.UTF8.GetBytes(unsafeContact));
Contact = serializer.ReadObject(stream) as Contact;
stream.Close();
}
catch (Exception)
{
// invalid contact
}
Contact class:
[DataContract]
public sealed class Contact
{
/// <summary>
/// Contact Full Name
/// </summary>
/// <example>John Doe</example>
[DataMember(Name = "name", IsRequired = true)]
[StringLength(100, MinimumLength = 1, ErrorMessage = #"Name length should be between 1 and 100.")]
public string Name {
get
{
return HttpUtility.HtmlEncode(_name);
}
internal set
{
Validator.ValidateProperty(value, new ValidationContext(this, null, null) { MemberName = "Name" });
_name = value;
}
}
private string _name;
// ...
}
Try to look look for WCF Data Annotations. WCFDataAnnotations allows you to automatically validate WCF service operation arguments using System.ComponentModel.DataAnnotations attributes.
http://wcfdataannotations.codeplex.com/
As an example, if I have a POCO for Forum and one for ForumPost, how can I elegantly return a list of ForumPosts and specify this right in the model. I'm doing it manually now by adding my db.Query call directly in the List property, but is there a better way?
[TableName("Forum")]
[PrimaryKey("ForumID")]
[ExplicitColumns]
public class Forum : BaseModel
{
[Column]
public int ForumID { get; set; }
[Column]
public string ForumName { get; set; }
[Column]
public string ForumDescription { get; set; }
[ResultColumn]
public List<ForumPost> {
get
{
// return list of ForumPost - what's a good way to handle this?
}
}
}
I wrote an static extension to this, so I can set this in my property like this (using some of my classes). This property would be in your POCO model:
private List<AssessmentAssignment> _AssessmentAssignments;
[ResultColumn]
public List<AssessmentAssignment> AssessmentAssignments
{
get
{
return ServiceExtensions<AssessmentAssignment>.GetRelatedList(this.GetType());
}
set
{
_AssessmentAssignments = value;
}
}
Here is the ServiveExtension that I wrote up to do it, but not sure i like this yet. It works, but meh. Anyone have any better ideas?
public static class ServiceExtensions<T> where T : class, new()
{
/// <summary>
/// Experimental way to retrieve a foreign key related list with PetaPoco
/// </summary>
/// <param name="PrimaryTableType"></param>
/// <returns></returns>
public static List<T> GetRelatedList(Type PrimaryTableType)
{
var primaryTableData = PocoData.ForType(PrimaryTableType);
var relationshipTableData = PocoData.ForType(typeof(T));
using (PetaPoco.Database db = new PetaPoco.Database("ConnStringName"))
{
PetaPoco.Sql sql = new PetaPoco.Sql("SELECT A.* FROM " + relationshipTableData.TableInfo.TableName + " A")
.Append("JOIN " + primaryTableData.TableInfo.TableName + " B ON A." + primaryTableData.TableInfo.PrimaryKey + " = B." + primaryTableData.TableInfo.PrimaryKey);
return db.Fetch<T>(sql);
}
}
}
I have begun to test Fluent NHibernate in C#
I have a well normalized object structure with 20 related classes.
I currently use Fluent 1.3 with NHibernate 3.2.
So far I have managed to use the AutoMap feature which suits me fine,
Very convenient!
BUT ...
3 of the tables are "enum tables" that need to have their records set with specific Id value.
I tried to make manual mappings of these tables and let the rest be automapped.
But when the manual table is created it fails because it references a table that is automapped (and not available for manual mapper?)
Is it possible to use AutoMapping but for some very few classes override identity creation on primary key?
I tried to make a custom convention but without success.
public class OverrideIdentityGeneration : Attribute
{
}
public class ConventionIdentity : AttributePropertyConvention<OverrideIdentityGeneration>
{
protected override void Apply(OverrideIdentityGeneration attribute, IPropertyInstance instance)
{
instance.Generated.Never();
}
}
Is there some other way?
It would be sad to be forced back to use manual mapping for all classes ....
class MyIdConvention : IIdConvention
{
public void Apply(IIdentityInstance instance)
{
if (instance.EntityType == ...)
{
instance.GeneratedBy.Assigned();
}
}
}
Update:
for enum-like classes it's often easier to define an enum as id
class ConfigValue
{
public virtual Config Id { get; set; }
}
// the convention is easy
if (instance.EntityType.IsEnum)
{
instance.GeneratedBy.Assigned();
// to save as int and not string
instance.CustomType(typeof(Config));
}
// querying without magic int values
var configValue = Session.Get<ConfigValue>(Config.UIColor);
I used the idea given by Fifo and extended it to use a custom attribute instead.
To make code readable and avoid redundance when using similar idea in other conventions I added an extension method to check for custom attribute.
This is the code I ended up with:
/// <summary>
/// Convention to instruct FluentNHIbernate to NOT generate identity columns
/// when custom attribute is set.
/// </summary>
public class ConventionIdentity : IIdConvention
{
public void Apply(IIdentityInstance instance)
{
if(instance.CustomAttributeIsSet<NoIdentity>())
instance.GeneratedBy.Assigned();
}
}
/// <summary>
/// Custom attribute definition.
/// </summary>
public class NoIdentity : Attribute
{
}
/// <summary>
/// Example on how to set attribute.
/// </summary>
public class Category
{
[NoIdentity]
public int Id { get; set; }
public string Name { get; set; }
}
public static class IInspectorExtender
{
/// <summary>
/// Extender to make convention usage easier.
/// </summary>
public static T GetCustomAttribute<T>(this IInspector instance)
{
var memberInfos = instance.EntityType.GetMember(instance.StringIdentifierForModel);
if(memberInfos.Length > 0)
{
var customAttributes = memberInfos[0].GetCustomAttributes(false);
return customAttributes.OfType<T>().FirstOrDefault();
}
return default(T);
}
}
I am trying to map same column to be an attribute and a relationship (for reasons that have to do with legacy data) using following mapping:
References(x => x.BaseProductTemplate, "ProductCodeTxt");
Map(x => x.DescriptionCode, "ProductCodeTxt")
.CustomType(typeof(TrimmedStringUserType));
but "System.IndexOutOfRangeException: Invalid index 9 for this SqlParameterCollection with Count=9." exception is thrown. How can I achieve this with NH without getting this error.
Here is a class:
public static MarketingPlanBaseProduct Create(BaseProductTemplate baseProductTemplate, ProductType productType)
{
var toReturn = new MarketingPlanBaseProduct();
toReturn.BaseProductTemplate = baseProductTemplate;
toReturn.Type = productType;
return toReturn;
}
protected MarketingPlanBaseProduct()
{
_coInsurancePercentages = new List<PlanCoInsurance>();
_benefits = new List<BaseProductBenefit>();
}
#region " Old system workaround "
/// HACK: In insight users were able to override description and the code, and system was displaying description from
/// the "BaseProduct" table, not from "ProductRef" table. In order to have this description display in Insight
/// during transitional period
/// we are modeling the MarketingPlanBaseProduct with two independent properties
/// that will be loaded based on the values in "ProductCodeTxt" and ProductNameTxt.
/// New MarketingPlanBaseProducts will however have description populated based on BaseProductTemplate ("ProductRef")
/// and code/description will not be changable from New System
/// Once old system is cut off, "DescriptionCode" Property should be removed,
/// "Name should be changed to be mapped property that derives value from BaseProductTemplate relationship
private string _descriptionCode;
public virtual string DescriptionCode
{
get
{
return _descriptionCode;
}
}
private string _name;
public virtual string Name
{
get { return _name; }
}
private void SetName(BaseProductTemplate baseProductTemplate)
{
_name = baseProductTemplate.Name;
_descriptionCode = baseProductTemplate.Code;
}
private BaseProductTemplate _baseProductTemplate;
public virtual BaseProductTemplate BaseProductTemplate
{
get
{
return _baseProductTemplate;
}
private set
{
_baseProductTemplate = value;
SetName(_baseProductTemplate);
}
}
You can also use Formula:
Map(x => x.MyProperty).Formula("propertyColumn").Not.Insert().Not.Update();
Since this was mapped on the view, I added one more column in the view with different name mapped to the same column, and it works.