Adding Prefix to property - asp.net-mvc-4

I am creating Web API where i am in need to add prefix to property. Is it possible to prefix some text with a property in controller. For eg. I am having a class A
public class Stats
{
pubic bool IsStat { get; set; }
}
public HttpResponseMessage GetStats(Stats data)
{
}
The Web method GetStats is accessed by passing data as below
{Stat: true}
Now what I need to add Is prefix to the Stat property and so i will be getting true value for IsStat property in class Stats. Is it possible ?

You have 2 options:
Rename your IsStat property to Stat. This should then match the json data.
Use [DataContract] and [DataMember] attributes on your Stats class and use the IsStat property to tell the deserializer that IsStat should get it's data from the Stat property.
[DataContract]
public class Stats
{
[DataMember(Name = "Stat")]
public bool IsStat { get; set; }
}

Related

How to bind a collection with objects?

I need to bind a collection of objects from a querystring, but I cannot find the proper querystring format.
My controller code:
public class Filter
{
public string Name { get; set; }
public string Operator { get; set; }
public object Value { get; set; }
}
public void Get(IEnumerable<Filter> filters)
{
....
}
If you do want to pass the objects with querystring you could try as below:
https://localhost:44389/Test/Index?filters[0].Name=n1&filters[1].Name=n2&filters[2].Name=n3&filters[2].Value=v3
The result:
the offcial document related:
https://learn.microsoft.com/en-us/aspnet/core/mvc/models/model-binding?view=aspnetcore-6.0#collections
but i don't think it's a good solution,because the length of Url is limited,if your model has plenty properties and your collection has many elements ,you may get some error

Asp.Net Core - multiple action methods with the same name and different parameters

I'm looking for a way to have more than one action method with the same name in controller without changing Url (route).
[HTTPPost]
Public ActionResult Method1 (Dto1 param)
{
}
[HTTPPost]
Public ActionResult Method2 (Dto2 param)
{
}
[HTTPPost]
Public ActionResult Method3 (Dto3 param)
{
}
This throws error -
Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException: The request matched multiple endpoints
Dto1, Dto2 and Dto3 derive from a base Dto, each have properties specific to different request methods. I am trying to avoid having a single method with a common Dto which will require multiple validations such as validating mandatory fields based on the value of other fields, etc. If we can have 3 different Post methods with different Dtos, it would makes things much easier
Adding Dtos (Simplified)
public class BaseDto
{
public string CommonProp1 { get; set; }
public string CommonProp2 { get; set; }
}
public class Dto1: BaseDto
{
public enumType Type = enumType.Type1;
public string Property1 { get; set; }
}
public class Dto2 : BaseDto
{
public enumType Type = enumType.Type2;
public string Property2 { get; set; }
}
public class Dto3 : BaseDto
{
public enumType Type = enumType.Type3;
public string Property3 { get; set; }
}
You can use Routes or calling a private method from the three above methods, you shouldn't do this as you want. I think your problem is more deep.
But.... if you still want it, here is a workaround.
Instead of receiving an object, receive a string with json content and parse the object.
But you will have to have a property inside the "json object" or another parameter that defines you wich object it is (Dto1, Dto2 or Dto3). In any case will be the same that use different routes or methods because objects are different.
[HTTPPost]
Public ActionResult Method (string param)
{
//Decode your string called param with JSON with a property inside
}
or
[HTTPPost]
Public ActionResult Method (string param, int type)
{
//Decode your string called param with JSON switching "type" as 1, 2 or 3
}
UPDATE after your update:
I suggest you receive BaseDto and the type in other parameter.
[HTTPPost]
Public ActionResult Method (BaseDto param, int type)
{
}

.NET Core - Json.NET Deserialisation Mapping

Is it possible to do mapping during the deserialization process of a JSON string to an object?
var resultObject = JsonConvert.DeserializeObject<ConfigItemGetResult>(result);
My JSON string is different from the object I want to deserialize to. So mapping has to happen. I'm trying to avoid making a model that maps 1 to 1 to the JSON string followed by mapping from object to object with for example AutoMapper.
Use Serialization Attributes for configuring your serialization mapping
public class JsonTest
{
[JsonProperty(PropertyName = "SomePropNameFromJson")]
public string SomeProp { get; set; }
[JsonProperty(PropertyName = "SomeNested")]
public SomeClass SomeClass { get; set; }
}
public class SomeClass
{
public SomeClass1 SomeClass1 { get; set; }
}
public class SomeClass1
{
public string text { get; set }
}
Here Json
{ "SomeProp":"value", "SomeNested":{
"SomeClass1":{
"text":"textvalue"
}
} }
Json convert trying to convert text to object by prop name with value via reflection if them finds prop name in text they take value if prop name has different name in JSON you can specify it via [JsonProperty(PropertyName = "SomeNested")] if this attr not set by default it will try get by prop name and it whatever what property is, it some object(your nested objects) or basic type, it will trying to convert it automaticaly.

Delegate the property display name translation to a handler

Current code in model:
[Display(Name = "E-mail")]
public string EMail { get; set; }
Desired code:
public string EMail { get; set; }
I would like to delegate the translation to a handler, something like this:
if(propertyName == "EMail") return "E-mail"
Based on my understanding of your question, I'm assuming that you are trying to implement localisation in your application.
If so, there are two options;
Resources
In .NET you can add Resource (.resx) files into your application to handle translation (one resx for each language). Then you can specify the Resource by specifying the ResourceType property of your Display attribute. For example;
public class Model
{
[Display(Name = "Email", ResourceType = typeof(Resources.Strings))]
public string Email { get; set; }
}
Custom attribute
Alternatively, if you are set on implementing this in a handler then you could implement a custom attribute, as demonstrated in this question.
Edit: Modified from the example in the above post.
If you add a new Resource file to your project - say Strings.resx and add "HelloWorld" as a field. You can then create a new attribute, such as LocalisedDisplayNameAttribute;
public class LocalisedDisplayNameAttribute : DisplayNameAttribute
{
public LocalisedDisplayNameAttribute(string resourceId)
: base(GetMessageFromResource(resourceId))
{
}
private static string GetMessageFromResource(string resourceId)
{
// "Strings" is the name of your resource file.
ResourceManager resourceManager = Strings.ResourceManager;
return resourceManager.GetString(resourceId);
}
}
You can then use it as follows;
public class Model
{
[LocalisedDisplayName("HelloWorld")]
public string Email { get; set; }
}
Let me know if I can help further,
Matt

Can I prevent a specific datamember from being deserialized?

I have a datacontract like this
[DataContract]
class MyDC
{
[DataMember]
public string DM1;
[DataMember]
public string DM2;
[DataMember]
public string DM3;
}
and sometimes I want to prevent DM2 from being deserialized when being returned from an OperationContract. Something like this:
[OperationContact]
public MyDC GetMyDC()
{
MyDC mdc = new MyDC();
if (condition)
{
// Code to prevent DM2 from being deserialized
}
return mdc;
}
I could always make a new DataContract that has only DM1 and DM3 and generate that from the MyDC instance but I want to see if it is possible to programatically remove DM2. Is it possible? How?
One way to do this is to set the EmitDefaultValue property of the DataMemberAttribute to false:
[DataContract]
class MyDC
{
[DataMember]
public string DM1;
[DataMember(EmitDefaultValue = false)]
public string DM2;
[DataMember]
public string DM3;
}
Then setting this property to null:
[OperationContact]
public MyDC GetMyDC()
{
MyDC mdc = new MyDC();
if (condition)
{
// Code to prevent DM2 from being deserialized
mdc.DM2 = null;
}
return mdc;
}
This way, that property doesn't get written to the output stream on serialization.
http://msdn.microsoft.com/en-us/library/aa347792.aspx
What you mean is serialization and not deserialization.
If you prepare a class for serialization applying the [DataContract] attribute to the class, only the members of the class that has [DataMember] attribute will be serialized:
[DataContract]
class MyDC
{
[DataMember]
public string DM1;
public string DM2;
[DataMember]
public string DM3;
}
In some more complex cases the usage of [IgnoreDataMember] can solve your problem. (See http://msdn.microsoft.com/en-us/library/ms733127.aspx)
By the way, you can serialize fields and properties, regardless of accessibility: private, protected, internal, protected internal, or public. You can serialize any read/write properties and not only fields. About serialization of collection types see http://msdn.microsoft.com/en-us/library/aa347850.aspx.
[DataContract]
class MyDC
{
[DataMember]
public string DM1;
public string DM2;
public bool IsDM2Serializable;
[DataMember(Name="DM2", EmitDefaultValue = false)]
public string DM2SerializedConditionally
{
get
{
if(IsDM2Serializable)
return null;
return DM2;
}
set { DM2=value; }
}
[DataMember]
public string DM3;
}
Then set IsDM2Serializable to false when you need to hide it:
[OperationContact]
public MyDC GetMyDC()
{
MyDC mdc = new MyDC();
if (condition)
{
// Code to prevent DM2 from being serialized
mdc.IsDM2Serializable = false;
}
return mdc;
}
Yes, we can prevent an attribute from serialization.
Put [DataContract] Annotation on class and [DataMember] for only serialized attribute. if you want to skip attribute when that attribute value is null then put [DataMember(EmitDefaultValue = false)] on that attribute.
Example:
[DataContract]
public class MyClass
{
[DataMember]
public int Id{ get; set; }
[DataMember]
public string Title { get; set; }
[DataMember]
public string MessageBody { get; set; }
[DataMember(EmitDefaultValue = false)]
public DateTime SentOn { get; set; }
}
Note: SentOn will be serialized when it is not null and others will be serialized in every condition.