I have a datacontract and in that i want to get the name of a property as mentioned in the code below.
[DataMember]
public string PhoneNumber { get; set; }
Now i am passing the values as
void GetMethod()
{
// takes PropertyName and Property values
ValidateMe("PhoneNumber", phoneObj.PhoneNumber.ToString();
}
Now i need to pass instead get the Property Name instead of Hardcoded "PhoneNumber"
How can i achieve this?
string GetPropertyName<TValue>(Expression<Func<TValue>> propertyId)
{
return ((MemberExpression)propertyId.Body).Member.Name;
}
By this way we can retrieve the Property Name
Related
I have a class (MyClass), in which there is a reference type field (let's call MyNestedClass).
I'm using Newtonsoft, and I would like to serialize this class, including this field. But instead of "opening a new block" in the Json (a Json object), I would like this field to remain in the same level as the other (primitive) fields of this class. It's guaranteed, that the MyNestedClass contains only one field.
public class MyClass
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("nested_prop", Required = Required.Always)]
public MyNestedClass NestedProp { get; set; }
...
}
public class MyNestedClass
{
public string Address { get; set; }
}
output (with some values):
{
"name" : "foo_val",
"nested_prop" : {
"Address" : "bar_val" // it gets its name (Address) by default (based on the prop name)
}
}
what I want:
{
"name" : "foo_val",
"address" : "bar_val"
}
(of course I have my reasons why do I need a separate class (MyNestedClass) instead of putting that string (Address) into the MyClass class)
I tried to create a converter (CustomCreationConverter) with overriding the WriteJson method, but it never gets called during the serialization process...
================================================
Edit:
I used CustomCreationConverter because I have already overridden its Create method (my prop type in my real problem is an interface, and not the concrete class)
As #dbc hinted, WriteJson hasn't been called because in CustomCreationConverter the CanWrite method is overriden with return false. Overriding also this method in my custom converer solves this problem.
So i have a REST API that works with a JSON based on OData exchange. In a OData type there is a ID property i want to read so i can do some checking on it. However when i want to write back to the webserver the ID property must not be present in the response JSON string. So it has to be a write-only property, but simply changing a property to write-only prevents be to check what the value is of that property.
For example, i create a new product:
Public Class Product
Public property ID as integer
Public property Title as string
End class
GET response:
{
"ID" = 1,
"Title" = "Cool product!"
}
POST Wrong:
{
"ID" = 1, <---- ignore this value
"Title" = "Cool product! Changed!"
}
POST Should be:
{
"Title" = "Cool product! Changed!"
}
The webserver uses OData
Using the attribute JsonIgnoredoesn't fix it because the value of the REST response isn't serialized then.
This is for WPF and not ASP.Net
JSON.NET supports conditional property serialization using a method that returns a bool and has the same name as the property with a ShouldSerialize prefix:
public class Product
{
public int Id { get; set; }
public string Title { get; set; }
public bool ShouldSerializeId() => false;
}
I have the following JSON:
[{
"theme-my-login":
{
"latest_version":"6.4.7",
"last_updated":"2017-01-06T18:14:00.000Z",
"popular":true,
"vulnerabilities":
[
{
"id":6043,
"title":"Theme My Login 6.3.9 - Local File Inclusion",
"created_at":"2014-08-01T10:58:35.000Z",
"updated_at":"2015-05-15T13:47:24.000Z",
"published_date":null,
"references":
{
"url":["http://packetstormsecurity.com/files/127302/","http://seclists.org/fulldisclosure/2014/Jun/172","http://www.securityfocus.com/bid/68254/","https://security.dxw.com/advisories/lfi-in-theme-my-login/"]
},
"vuln_type":"LFI",
"fixed_in":"6.3.10"
}
]
}
},{
"other-item":
{
"latest_version":"6.4.7",
"last_updated":"2017-01-06T18:14:00.000Z",
"popular":true,
"vulnerabilities":
[
{
"id":6043,
"title":"Theme My Login 6.3.9 - Local File Inclusion",
"created_at":"2014-08-01T10:58:35.000Z",
"updated_at":"2015-05-15T13:47:24.000Z",
"published_date":null,
"references":
{
"url":["http://packetstormsecurity.com/files/127302/","http://seclists.org/fulldisclosure/2014/Jun/172","http://www.securityfocus.com/bid/68254/","https://security.dxw.com/advisories/lfi-in-theme-my-login/"]
},
"vuln_type":"LFI",
"fixed_in":"6.3.10"
}
]
}
}]
json2csharp says the object model should look like this, but that's clearly not correct
public class References
{
public List<string> url { get; set; }
}
public class Vulnerability
{
public int id { get; set; }
public string title { get; set; }
public DateTime created_at { get; set; }
public DateTime updated_at { get; set; }
public object published_date { get; set; }
public References references { get; set; }
public string vuln_type { get; set; }
public string fixed_in { get; set; }
}
public class ThemeMyLogin
{
public string latest_version { get; set; }
public DateTime last_updated { get; set; }
public bool popular { get; set; }
public List<Vulnerability> vulnerabilities { get; set; }
}
public class RootObject
{
public ThemeMyLogin __invalid_name__theme-my-login { get; set; }
}
that I am trying to deserialise into c# classes using Json.NET, but as the top level item doesn't have a traditional name:value pair (the name effectively is "theme-my-login" and the value is the object), it's not deserialising.
Any pointers on how I can get this to deserialise? Do I need to use a custom deserialiser?
The reason I cannot use a dictionary as suggested in How can I parse a JSON string that would cause illegal C# identifiers? is that I need the value "theme-my-login" as one of the values in my model as it defines the object. I have added a second item into the json as this will be a list of items. I previously only included one to show the item structure.
You need to deserialize to List<Dictionary<string, ThemeMyLogin>> like so:
var root = JsonConvert.DeserializeObject<List<Dictionary<string, ThemeMyLogin>>>(json);
The code-generation site http://json2csharp.com/ has some limitations of which you need to be aware:
The JSON standard allows for two types of container:
The array, which is an ordered collection of values. An array begins with [ (left bracket) and ends with ] (right bracket). Values are separated by , (comma).
The object, which is an unordered set of name/value pairs. An object begins with { (left brace) and ends with } (right brace).
If your root container is an array, http://json2csharp.com/ will auto-generate a RootObject model to deserialize each object in the array. To actually deserialize the entire array you need to deserialize to a collection of root objects such as a List<RootObject>. See Serialization Guide: IEnumerable, Lists, and Arrays.
When a JSON property corresponds to an invalid c# identifier, http://json2csharp.com/ will "helpfully" add a property to the containing type that looks like this:
public PropertyType __invalid_name__my-invalid-identifier { get; set; }
Of course this will not compile, so you need to notice any __invalid_name properties and manually fix the generated code. Options for doing this include those covered in How can I parse a JSON string that would cause illegal C# identifiers? and elsewhere:
If the property name is fixed and known in advance, rename the c# property to something valid consistent with your coding conventions and mark it with [JsonProperty("my-invalid-identifier")]. (From the answer by ken2k).
If the containing type consists entirely of variable property names with a fixed schema for their values corresponding to some type T, replace the containing type with a Dictionary<string, T>. (From the answer by L.B.)
If the containing object has a mixture of fixed and variable properties, see Deserialize json with known and unknown fields or How to deserialize a child object with dynamic (numeric) key names?.
You seem to have encountered both limitations. Working sample .Net fiddle.
Maybe the question was already asked, but the answer that i found is not clear.
I would like to select a Default Value of my Dropdown list.
I have a list of Countries and based on the Region Code retreive via Thread.CurrentThread.CurrentCulture, I would like to select the country of the user.
Will it be possible via my approach:
View
#model Question
#Html.DropDownListFor(b => b.SelectedAnswer,new SelectList(Model.Answers,"ID","Country"))
Model
public class Question
{
public int ID { get; set; }
public string Country { get; set; }
public List<Answer> Answers { get; set; }
[Required]
public int SelectedAnswer { get; set; }
public int Order { get; set; }
public Question()
{
Answers = new List<Answer>();
}
}
Thank you.
I was going to add this as a comment, but the length is too long, and this way if I'm helpful you can accept this as an answer.
This is the method I use to implement this;
First, within the viewmodel I have the following
public int FooID { get; set; }
public IEnumerable<SelectListItem> FooList { get; set; }
FooID being both the default value (or currently selected) and the property used to gather the post result.
I have a function to build FooList, which returns the type of
List, using this format for each item:
new SelectListItem { Text = i.Name, Value = i.FooID.ToString() };
Before outputting the viewmodel, the current value is inserted into FooID, or if this is for a new item, I will generally set the value to 1, the default value.
Then for the output;
#Html.DropDownListFor(m => m.FooID, Model.FooList)
Just remember that FooID will be passed over as a string, so will need to be gathered as a string FooID parameter, and converted to Int. As long as FooID is set before the viewmodel is passed to the view from the controller, the item within FooList whose value equals FooID will be set as the default ... Such as;
public ActionResult MyAction()
{
MyVM vm = new MyVM();
vm.FooID = 1;
vm.FooList = FunctionToGenerateFooList();
return View(vm);
}
Really, you should be passing your dropdown list as a list holding SelectListItem. Then for each country, have the text as the country code and assign it an id within value. Then, when you initialise the model, gather the culture, and find which item within the list has a Text that matches
Thread.CurrentThread.CurrentUICulture.Name;
and assign it's value property to SelectedAnswer.
I have an object which I am de-serializing using ToJson<>() method from ServiceStack.Text namespace.
How to omit all the GET only propeties during serialization? Is there any attribute like [Ignore] or something that I can decorate my properties with, so that they can be omitted?
Thanks
ServiceStack's Text serializers follows .NET's DataContract serializer behavior, which means you can ignore data members by using the opt-out [IgnoreDataMember] attribute
public class Poco
{
public int Id { get; set; }
public string Name { get; set; }
[IgnoreDataMember]
public string IsIgnored { get; set; }
}
An opt-in alternative is to decorate every property you want serialized with [DataMember]. The remaining properties aren't serialized, e.g:
[DataContract]
public class Poco
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
public string IsIgnored { get; set; }
}
Finally there's also a non-intrusive option that doesn't require attributes, e.g:
JsConfig<Poco>.ExcludePropertyNames = new [] { "IsIgnored" };
Dynamically specifying properties that should be serialized
ServiceStack's Serializers also supports dynamically controlling serialization by providing conventionally named ShouldSerialize({PropertyName}) methods to indicate whether a property should be serialized or not, e.g:
public class Poco
{
public int Id { get; set; }
public string Name { get; set; }
public string IsIgnored { get; set; }
public bool? ShouldSerialize(string fieldName)
{
return fieldName == "IsIgnored";
}
}
More examples in ConditionalSerializationTests.cs
For nullable members, you also have the ability to set it to null before serializing.
This is particularly useful if you want to create a single view/api model that is re-used for several API calls. The service can touch it up before setting it on the response object.
Example:
public SignInPostResponse Post(SignInPost request)
{
UserAuthentication auth = _userService.SignIn(request.Domain, true, request.Username, request.Password);
// Map domain model ojbect to API model object. These classes are used with several API calls.
var webAuth = Map<WebUserAuthentication>(auth);
// Exmaple: Clear a property that I don't want to return for this API call... for whatever reason.
webAuth.AuthenticationType = null;
var response = new SignInPostResponse { Results = webAuth };
return response;
}
I do wish there was a way to dynamically control the serialization of all members (including non-nullable) on a per endpoint fashion.