Reuse Model from another project - c#

I've got a Custom Validator Attribute called RequiredIf inside a Model in my main Web Project and I need to reuse that model in another Model from another project. When I look at the disassembled dll from the Main Project inside the subproject, the Custom Attribute just disappears and the Custom Attribute doesn´t work.
Here goes my structure:
MainProject
[RequiredIf( "TipoReagendamentoSco", false, "CodigoTipoReagendamento", null, "Tipo Reagendamento é obrigatório")]
[Display(Name = "Tipo Reagendamento:")]
public int CodigoTipoReagendamento { get; set; }
SubProject
public TipoReagendamentoModel TipoReagendamento { get; set; }
Disassembled MainProject.DLL
[Display(Name = "Tipo Reagendamento:")]
public int CodigoTipoReagendamento { get; set; }
The Custom Validator Attribute (RequiredIf) went away. But when I use 'Required' from DataAnnotations (not a custom attribute), it works like a charm.
Thanks !

Related

Model binder for abstract class reference within abstract class asp.net core mvc 3

I'm following along at Model binder for abstract class in asp.net core mvc 2, but my model doesn't bind the HostedControls in ConcreteControlHost (see below). If I change the type of HostedControls to ConcreteControlText[], it does bind. I'd like to keep it as AbstractControl[] so that I can host multiple types of control.
I know the abstract binder is working because MainModel.Controls binds.
While debugging the binding of ConcreteControlHost, binder._propertyBinders has an entry for HostedControls as follows:
{[ModelMetadata (Property: 'ConcreteControlHost.HostedControls' Type: 'AbstractControl[]'), {Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ArrayModelBinder<MyProject.AbstractControl>}]}
Following that property (Value.ElementBinder.Inner) eventually leads to AbstractModelBinder.
Breakpoints in AbstractModelBinder are not hit when binding the properties of ConcreteControlHost, but are when binding the properties of MainModel (as in, I get the hits for ConcreteControlHost, but not for ConcreteControlText).
This isn't related to In an Editor Template call another Editor Template with the same Model because it isn't the same model, and because everything renders correctly, it just doesn't bind. None of the ConcreteControlTexts referenced by HostedControls are referenced directly by MainModel.Controls.
public class MainModel {
public AbstractControl[] Controls;
}
public abstract class AbstractControl {
public string TypeName { get; set;}
}
public class ConcreteControlText: AbstractControl {
public string Text { get; set; }
}
public class ConcreteControlHost: AbstractControl {
public AbstractControl[] HostedControls { get; set; }
}
Does anyone see what I need to change to allow model-binding to work on ConcreteControlHost.HostedControls?
Turns out in my actual code, HostedControls had { get; private set; }. Removing the private modifier on the setter made it work.
Jeremy, thanks for looking into this.

How to use Metadata validation in blazor?

I have a project include two project in same Solution Explorer
First: DbModelContextProvider (Class library)
Second: AppApiProvider (MVC core api -v3.1.4)
In DbModelContextProvider project i want create Metadata validation for Department
public class DepartmentMetaData
{
[Display(Name = "Department Name")]
[Required]
public string Name { get; set; }
}
Then create new class Department but partial class
[MetadataType( typeof(DepartmentMetaData))]
public partial class Department
{
}
Same code use with MVC core web app work success but when i want work
with Blazor not work
It seems it is not yet supported for Blazor. https://github.com/dotnet/aspnetcore/issues/20805

Reinforced.Typings cannot handle attributes on properties

I have an ASP.NET Core project using ASP.NET Identity. Some classes cannot be exported since their properties contain attributes from System.ComponentModel.DataAnnotations. If I ignore such properties, everything works fine.
Example class:
public class LoginViewModel
{
[Required]
[EmailAddress]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
Since I don't want to strip out these attributes, what is the recommended course of action?
[assembly: TsGlobal(
CamelCaseForMethods = true,
CamelCaseForProperties = true,
GenerateDocumentation = true,
UseModules = true,
DiscardNamespacesWhenUsingModules = true)]
namespace X
{
public static class ReinforcedTypingsConfiguration
{
public static void Configure(ConfigurationBuilder builder)
{
builder
.ExportAsInterface<LoginViewModel>()
.AutoI(false)
.WithProperty(x => x.RememberMe)
;
}
}
}
Other than that, it seems that UseModules does the opposite of what I want it to do. When set to true, the generated ts file doesn't contain any modules. When set to false, I get module in my ts files.
Also, when dividing types among files, I get strange folder names on mac that contain \ for every . in my namespace. Can I just flatten out the structure? And completely ignore backend namespaces?
In the above configuration (and I use file splitting) I get the annoying error message error MSB3552: Resource file "**/*.resx" cannot be found..
Upgrade to 1.4.2 to fix this issue.

How do I prevent Entity Framework forcing validation on child object properties?

I have an ASP.NET MVC 3 project that uses .Net 4.0 Framework and Entity Framework 4.4. I am using the code first w/ migrations approach for the Entity Framework.
I have an object A that has a property of object B. object A really just needs to know the id for object B, but MVC is enforcing all annotation validations on object B as I've marked it required in object A (which it is). ModelState.IsValid is always returning false because some validations are failing on object B when the form is submitted.
Example:
public class FormField
{
public int Id { get; set; }
[MaxLength(50)]
[Required]
[DisplayName("Field Name")]
public string Name { get; set; }
[Required]
public Form Form { get; set; }
}
public class Form
{
public Form()
{
Fields = new List<FormField>();
}
public int Id { get; set; }
[Required]
public string Name { get; set; }
public List<FormField> Fields { get; set; }
}
This isn't a problem when editing an existing FormField as I can just put a hidden field with the Form.Name property on the page (this still strikes me as something that should be unnecessary). The issue arises when creating a new FormField. I display a drop down list of forms (this is populated from my view model), and make that field point to the FormField.Form.Id property. ASP .NET MVC is still expecting formField.Form.Name (as this was marked as required on the Form object).
If I remove the "[Required]" annotation from the Form field of the FormField object, the validations wouldn't fire, but this would make the foreign key to Form.Id nullable in the database, which it shouldn't be.
Any thoughts? I'm probably doing something wrong here but I'm not entirely sure what.
I removed the [Required] annotation on FormField.Form. That didn't fix the issue. I tried adding "[Bind(Exclude = "vm.FormField.Form")]" to the parameter being posted. This stops the binding, but ensures I'm still left with the validation errors in ModelState.
Ultimately, I had to do:
ModelState.Remove("FormField.Form.Id");
ModelState.Remove("FormField.Form.Name");
And this prevented the ModelState errors I was getting. As I really only need the Form.Id, I had a property in my ViewModel "SelectedForm" and use this property for that value.
So...this works, but...this seems a pretty tedious solution as if I had more required fields on the FormField.Form object, I would have to list each one as well as hard code the property name in a string form.
Can anyone think of a way to refine this approach?
Maybe you could remove the [Required] attribute and instead use the EF fluent API to configure this:
modelBuilder.Entity<FormField>().Property(ff => ff.Form).IsRequired();

Can ASP.Net MVC 2 Custom attributes on class level and on property level be active in the same time?

I am working on asp.net mvc 2 web application.
I have model with 3 properties:
[IsCityInCountry("CountryID", "CityID"]
public class UserInfo
{
[Required]
public int UserID { get; set; }
[Required]
public int CountryID { get; set; }
[Required]
public int CityID { get; set; }
}
I have one "required" property attribute, and one attribute on class level :
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class IsCityInCountry : ValidationAttribute
{
public IsCityInCountry(string countryIDProperty, string cityIDProperty)
{
CountryIDProperty = countryIDProperty;
CityIDProperty = cityIDProperty;
}
public string CountryIDProperty { get; set; }
public string CityIDProperty { get; set; }
public override bool IsValid(object value)
{
var properties = TypeDescriptor.GetProperties(value);
var countryID = properties.Find(CountryIDProperty, true).GetValue(value);
var cityID = properties.Find(CityIDProperty , true).GetValue(value);
int countryIDInt;
int.TryParse(countryID.ToString(), out countryIDInt);
int cityIDInt;
int.TryParse(cityID.ToString(), out cityIDInt);
if (CountryBusiness.IsCityInCountry(countryIDInt, cityIDInt))
{
return true;
}
return false;
}
}
When I post the form on my view, and CountryID is not entered, in ModelState dictionary there's an error about that issue. Other attribute is ignored ("IsCityInCountry"). When I choose CountryID and CityID, which is not in selected country, I get appropriate validation message about that, and ModelState has another key (which is ""). I understand that advantage have property attributes and then class attributes. My question; is there any way to get all validation messages at the same time, no matter what kind of attributes are involved (class or property attributes)? Thanks in advance.
ASP.NET MVC won't perform class level validation if there are property level validation errors. Brad Wilson explains this in his blog post:
Earlier today, we committed a change to MVC 2 that converted the
validation system from Input Validation to Model Validation.
What this means is that we will always run all validators on an
object, if that object had at least one value bound into it during
model binding. We run the property-level validators first, and if all
of those succeed, we'll run the model-level validators.
I would recommend you to go ahead and checkout FluentValidation.NET if you want to perform some more advanced validation in an ASP.NET MVC application. Declarative validation simply doesn't fit the bill in advanced validation scenarios.

Categories

Resources