I've a model class below:
class Person
{
string FirstName {get;set}
string ABNNumber {get;set}
}
This object gets sent to UI via JsonResult. The problem is I don't want to sent ABNNumber to UI due to security risk.
Is there anyway (any attribute) which I can use to achive above?
Thanks
Use attribute [ScriptIgnore]. It will help:
class Person
{
string FirstName {get;set}
[ScriptIgnore]
string ABNNumber {get;set}
}
Related
I am creating an ASP.NET MVC application.
I have a model with data annotations like this:
public class SearchModel
{
[MaxLength(11)]
public string? SSN { get; set; } = string.Empty;
}
And I have a controller method that receives an object of this type as parameter:
public async Task<IActionResult> Search([Bind(include: "SSN")] SearchModel searchModel)
{
// do something
}
I get a Veracode error
ASP.NET misconfiguration : improper model validation (CWE ID 1174)
on the definition of the method...
Testing.. If I replace SearchModel with String, it works. So the problem is the model definition, but I added the data annotations to the property.
What else can I check?
Thanks
As I found here the only way to avoid this flaw is to remove signature Async Task<> from the Method..
Model:
public class Person : IValidatableObject
{
public Address ResidentialAddress { get; set; }
public Address PostalAddress { get; set; }
}
public class Address
{
public string Address1 { get; set; }
}
in Model:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (string.IsNullOrWhiteSpace(PostalAddress.Address1))
{
yield return
new ValidationResult("Postal address is required",
new[] { nameof(PostalAddress.Address1) });
}
}
View: (A partial view for address inside the View for Person)
#Html.ValidationMessageFor(m => m.Address1)
In the html this comes out with the name PostalAddress.Address1 and the id PostalAddress_Address1
Unfortunately nameof(PostalAddress.Address1) just returns Address1.
I have tried replacing it with PostalAddress.Address1 and PostalAddress_Address1 and can't get the error to show up.
What's the secret?
I think #MikeDebela is right in the comment below your answer. Your model needs to implement IValidatableObject if you're going to use custom model validation like that. However, that's not your only problem.
First, is there a particular reason you're not just relying on the [Required] attribute for this? Custom model validation is a bit of a waste for something this simple. If the issue is that this is your actual entity class, and you don't want the Address1 column non-nullable at the database-level, well, that's what view models are for. Use them. You can make the property required on just your view model. As a best practice, you should never utilize your entity classes directly to post to.
Also, you're never newing up PostalAddress. When the model binder does its thing on post, if no properties of a related class are posted, it leaves the value of the that related class as null. Then, any related classes that are null, are also not validated. As a result, if the only property is Address1 and you don't post Address1, then PostalAddress is null, and no property on it, specifically, Address1, will participate in validation.
I have a test app that works perfectly with the following classes in one app, but not in another:
public class ValueChange
{
public int GroupId { get; set; }
public List<ItemValueChange> Changes { get; set; }
}
public class ItemValueChange
{
public int ItemId { get; set; }
public string Value { get; set; }
public string Key { get; set; }
}
My plugin posts a JS structure that matches this structure (changes is a jQuery array).
The raw post data (from Fiddler2) looks like:
GroupId 1000
Changes[0][Value]
Changes[0][Key]
Changes[0][ItemId] 1
In the test app this works and maps the data sent to a ValueChange object correctly.
[HttpPost]
public JsonResult Validate(ValueChange change)
{
// The Changes property has the required array of objects/properties
}
In our main application, to which I just ported the plugin and classes, the post data sent looks like:
GroupId 3705
Changes[0][Value]
Changes[0][Key]
Changes[0][ItemId] 81866
and the validate method called looks identical:
[HttpPost]
public JsonResult Validate(ValueChange changes)
{
// changes contains a null list and no GroupId
}
If I break-point this method changes is non-null object with a GroupId of 0 and no child elements in Changes. I can however see these values available from Request.Form in the debugger:
Request.Form["GroupId"] "3705" string
Request.Form["Changes[0][Key]"] "" string
Request.Form["Changes[0][ItemId]"] "81866" string
Request.Form["Changes[0][Value]"] "" string
Q. What would cause the automapping to not work in a different MVC project with the type of data?
If I simplify ValueChange to this (below) it starts working and receives GroupId values:
public class ValueChange
{
public int GroupId { get; set; }
}
If I send JS object data without a changes property it works e.g.
{ GroupId: 123 }
Something about the list called Changes is causing the mapping to fail. I have tried it as an array and also sending a single hard-wired entry from JS like this (still fails):
{ GroupId: 123, Changes: [{ItemId: 456, Value: "V", Key: "K"}]
OMG. The auto-mapper will ignore properties if a property name matches the parameter name!!!
It was caused simply by having the parameter called changes (vs. change in the test app) when a property of the received data was also called changes.
Solution: I changed the parameter name e.g.
[HttpPost]
public JsonResult Validate(ValueChange valueChange)
{
}
To clarify, this problem occurs is a first-level property of the data passed matches a parameter name. If it were a nested property tit would not attempt to match the parameter name.
This little detail needs to be stapled to everyone's desk/hand/head.* :)
I am getting this error when attempting to use a Web API controller.
Web API Error: The 'ObjectContent`1' type failed to serialize the response body for content type
the code in my controller is as follows
public IEnumerable<Student> GetAllStudents()
{
var allstudents = unitOfWork.StudentRepository.Get(includeProperties: "Groups");
return allstudents;
}
public Student GetStudentByID(Guid id)
{
return unitOfWork.StudentRepository.GetByID(id);
}
and my 'Student' class is as follows
public partial class Student
{
public Student()
{
this.Groups = new HashSet<Group>();
}
public System.Guid StudentID { get; set; }
public string Surname { get; set; }
public string FirstName { get; set; }
public byte[] Timestamp { get; set; }
public virtual Course Course { get; set; }
public virtual ICollection<Group> Groups { get; set; }
}
Both methods result in the same error.
My inner exception is as follows
Type
'System.Data.Entity.DynamicProxies.Student_4C97D068E1AD0BA62C3C6E441601FFB7418AD2D635F7F1C14B64F4B2BE32DF9A'
with data contract name
'Student_4C97D068E1AD0BA62C3C6E441601FFB7418AD2D635F7F1C14B64F4B2BE32DF9A:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies'
is not expected. Consider using a DataContractResolver 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 DataContractSerializer.
I have a feeling I need to use the KnownType attribute but I'm not exactly sure how to implement it.
Any help would be appreciated
If you don't need the lazy-loaded navigation properties provided by the proxy class (System.Data.Entity.DynamicProxies.Student_4C97D068E1A...), you can disable their generation by setting:
unitOfWork.Configuration.ProxyCreationEnabled = false;
What to do if you need the proxy class is another question.
Follow these links for a good overview of lazy loading and proxies:
Loading Related Entities
Working with Proxies
Should I enable or disable dynamic proxies
I usually disable lazy loading and proxies by default, and enable one or both in specific code blocks that need them.
What is the inner exception message? The inner exception message will be the actual exception that is thrown by the serializer and it should tell us which type is causing the exception.
Let me guess -- Is it any the type Course and the type Group? If so, try putting KnownType attribute on the actual implementation type of your class Student
[KnownType(typeof(GroupA))]
[KnownType(typeof(CourseA))]
public partial class Student
{...}
public class GroupA : Group {...}
public class CourseA : Course {...}
public interface Group {...}
public interface Course {...}
I'm using ValueInjecter to flatten/unflatten view models into domain objects created by Entity Framework (4.3.1) model-first. All of my VARCHAR columns in my database are NOT NULL DEFAULT '' (personal preference, no desire to open up a holy war here). On post, the view model comes back with any string property that has no value as null, so when I attempt to inject it back into my domain model class, EF barks at me for attempting to set a property with IsNullable=false to null. Example (over-simple):
public class ThingViewModel
{
public int ThingId{get;set;}
public string Name{get;set;}
}
public class Thing
{
public global::System.Int32 ThingId
{
//omitted for brevity
}
[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
[DataMemberAttribute()]
public global::System.String Name
{
//omitted for brevity
}
}
Then, my controller post looks like this:
[HttpPost]
public ActionResult Edit(ThingViewModel thing)
{
var dbThing = _thingRepo.GetThing(thing.ThingId);
//if thing.Name is null, this bombs
dbThing.InjectFrom<UnflatLoopValueInjection>(thing);
_thingRepo.Save();
return View(thing);
}
I'm using UnflatLoopValueInjection because I have nested types in the actual domain version of Thing. I attempted to write a custom ConventionInjection to convert null strings to string.Empty, but it appears that UnflatLoopValueInjection switches it back to null. Is there a way I can get ValueInjecter not to do this?
Nuts, I just figured it out with help from the wiki. The solution appears to be to extend UnflatLoopValueInjection:
public class NullStringUnflatLoopValueInjection : UnflatLoopValueInjection<string, string>
{
protected override string SetValue(string sourceValue)
{
return sourceValue ?? string.Empty;
}
}