Value tuples expose wrong parameter name from WebAPI - c#

I'm using web api. I've been a bit lazy and decided to return a value tuple from my controller.
[HttpGet]
[Route(AuthAPIRoutes.GET_MFA_DEVICES)]
public (string Type, string Value)[] GetMultiFactoryMethods()
{
return GlobalFactory<IPaystreamMFASecurityService>.Instance.GetMultiFactorMethods();
}
The JSON response doesn't seem to be using the appropriate naming is this being optimized away?
{
"item1": "Phone",
"item2": "1-512-555-0550"
}
NOTE: I'm aware I can explicitly make a model to avoid this problem. I would like to understand what is occurring and why aren't my value tuple names being respected in the response?

What is occurring is that ValueTuple as a type (a group of generic types, actually) is actually very static, and has properties named things like Item1, Item2, etc.
The nice syntax you get from C# where you can declare a name and have it used elsewhere in your code is simply a feature of the C# language. The compiled code referencing those values by name ends up calling into those static properties (Item1, e.g.). And in fact, you can still access those properties by their "Item" names in your own C# code.
From the compiled code's perspective, the only clue about the names of the fields on those tuples is an attribute that gets associated with the method, so unless ASP.NET passed contextual information about the action method into the serializer, there would be no way for the serializer to know what names those properties were supposed to have.
See this article for an in-depth look at what ValueTuples are doing under the hood.

Related

Proper Naming Convention For Parameter of Type List<long>

I wrote a method in c# which takes the input parameter of type List and i kept the parameter variable name as cardIDList.
And from code review feedback, they asked me to change the parameter variable name from cardIDList to cardIDs saying that appending list is not a right naming convention from Microsoft standard.
I tried to find the truthiness of that feedback in google, but I couldn't find like that anywhere. I need the help on this.
From :
public void DoSomething(List<long> cardIDList)
To :
public void DoSomething(List<long> cardIDs)
Common naming conventions can be found here https://github.com/ktaranov/naming-convention/blob/master/C%23%20Coding%20Standards%20and%20Naming%20Conventions.md
and here:
https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/naming-guidelines
https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/naming-parameters says:
CONSIDER using names based on a parameter’s meaning rather than the
parameter’s type.
First of all - why do you take List as a parameter? You should allow the parameter to be as generic as possible - if you only need collection of elements and their count, use ICollection. Even better IEnumerable if you want to only iterate through the list or IReadOnlyCollection if you want to avoid accidental item change. It will be much easier to write unit tests for this method or override it in the future.
As you can see, type of parameter can be changed in the future and it shouldn't affect the naming. Putting "list" in the parameter name is redundant because we already know the type of that parameter. Now what should you do if you want for example to change the type to IEnumerable? Change it to cardIDEnumerable?

Access <AnonymousType> fields

I have an AnonymousType object that contacts two fields with their values. How can I access the value of these fields?
Ex:
SourceTypeObject { Source_Type_Id = 1, Source_Type_Name = "bibliography" }
I need to do something like : SourceTypeObject.Source_Type_Id
Is that possible?
EDIT:
Here's what I get if I tried to access the property directly:
Yes, this is the exact purpose of anonymous types. The only thing that might prevent you from doing so is if you passed the anonymous type around as a parameter with type "object". This would hide information about the anonymous type, and it would look like just any old object then.
The only recourse if this is the case is to use reflection, which is slow and awkward. Anonymous types are a meant to be a very "local" phenomenon, and if you find yourself wanting to use them elsewhere in the program, it's worth the time to promote it to a real type.
EDIT: In response to the image you posted, assuming the array is declared locally just outside of view, try to replace the object SourceTypeObject with var SourceTypeObject. This allows it to infer the anonymous type instead of being told that it's an object.

List<dynamic> elements have fields but I cannot access them. Why?

I need to loop over a List<dynamic> objects.
The list's objects all have values, but for some reason, I am not able to access any of the dynamic object fields. Below is a screenshot of my debug window:
There you can see the object contains fields (such Alias, Id, Name, etc).
I tried both casting it to a IDictionary<string, object> and ExpandoObject, to no avail. I did not face such a thing before: failing to access existing fields in a dynamic object when they exist.
What is wrong here?
The code is throwing a Microsoft.CSharp.RuntimeBinder.RuntimeBinderException with a message stating {"'object' does not contain a definition for 'Name'"}.
The list was created adding anonymously-typed objects, like this:
return new List<dynamic>(fields.Select(field => new
{
Id = field.Id,
Alias = field.Alias,
Name = field.Name,
Type = field.Type,
Value = field.Value,
SortOrder = field.SortOrder
}));
where fields is an ICollection<Field>, a strongly-typed collection.
The telling part is the exception:
{"'object' does not contain a definition for 'Name'"}.
This indicates that the runtime binder was not actually capable of accessing the type you're passing in dynamic (since dynamic does actually enforce visibility rules).
The most likely cause of this is that you're creating the anonymous type in a different assembly from the one where you're subsequently reading it - since anonymous types are declared internal, the consuming assembly cannot access it, causing the error message above.
Contrast with the usual case of runtime binder exceptions:
'<>f__AnonymousType0< string >' does not contain a definition for 'Name'
EDIT:
A possible solution to the problem is to use the InternalsVisibleToAttribute on the assembly containing the anonymous type. However, this is code smell - just like any other use of InternalsVisibleToAttribute or internal itself.
A better way would be to make sure you don't actually pass anonymous types over assembly boundaries - after all, they shouldn't even be used outside of the method they originated from; the fact that they are is basically an implementation detail of .NET - they didn't have another way to do the same thing. This could change in future versions, making the InternalsVisibleToAttribute solution doubly unreliable.
The way your code is using dynamic suggests that your team has flawed assumptions about how dynamic works and how it's supposed to be used. Note how the actual runtime type of List<dynamic> is actually List<object>. The same goes for arguments of type dynamic (which are again just object, albeit marked with DynamicAttribute). And in fact, that really is what dynamic is - it's a way to handle runtime dynamic dispatch - it's not a property of the type or anything, it's just the way you actually invoke whatever you're trying to invoke. For C#, dynamic allows you to skip most of the compiler checks when working with those dynamic types, and it generates some code to handle the dispatch for you automatically, but all of that only happens inside the method where you actually use the dynamic keyword - if you used List<object>, the end result would be exactly the same.
In your code, there's no reason not to use simple static types. Dynamic typing doesn't really give you any benefits, apart from the effort to code the types themselves. If your co-workers don't like that, well, they should present a better solution - the problem is quite obvious, and it's something you need to deal with.
Much worse, it explicitly hides all context, all the type information. That's not something you want in an API, internal or not! If you want to hide the concrete types being used, why not - but you should still expose an interface instead. I suspect this is the reason why anonymous types can't implement interfaces - it would encourage you to go entirely the wrong way.

Redundant explicit property name in C# warning

I am using the SimpleMembership provider and adding additional fields to be saved on registration.
To save additional fields on registration I use the method used everywhere e.g. Seed Users and Roles with MVC 4, SimpleMembershipProvider, SimpleRoleProvider, Entity Framework 5 CodeFirst, and Custom User Properties.
I use the following SimpleMembership provider method called in my HttpPost ActionResult Register method.
WebSecurity.CreateUserAndAccount(registerModel.UserName, registerModel.Password,
new { FirstName = registerModel.FirstName, LastName = registerModel.LastName, CompanyName = registerModel.CompanyName});
Additional fields get added by a by value method parameter of type object. The description for this is "A dictionary that contains additional user attributes"
This works, but I have JetBrains ReSharper 8 installed and for the property names I get "redundant explicit property name" warnings.
To remove the warnings I changed my code to:
WebSecurity.CreateUserAndAccount(registerModel.UserName, registerModel.Password,
new { registerModel.FirstName, registerModel.LastName, registerModel.CompanyName});
My questions are:
1) for this anonymous object parameter where I now remove the property names so I don't get the Resharper warnings anymore, how does it know what the property names will be use to match to the db property class, since they are passed by value?
2) what is best practice having the property names in or not. Having them not in is not very readable and in code samples they are specified, so I would imagine having them in is better for readability rather than removing it.
My question are 1) for this anonymous object parameter where I now remove the property names so I don't get the Resharper warnings anymore, how does it know what the property names are since they are passed by value?
The names are inferred (by the compiler) from the expressions. This only works when you're using a field or property (not a literal or a method for example). This is in section 7.6.10 of the C# language specification.
2) what is best practice having the property names in or not. Having them not in is not very readable and in code samples they are specified so I would imagine having them in is better rather than removing it
If it's more readable for you and your team to always include the name, then go ahead and do so. For other people, it may feel a little redundant. Just adjust your R# settings to fit your local conventions.
Your argument that "in code samples they are specified" is specious though - there are some examples where they're specified and some where they're not. I suspect you'll find a mixture even within particular example providers (e.g. in MSDN).
When you set up your propertyNames object you're creating an instance of an anonymous Type - when you do that you can leave out the property name if it's the same as the property from which you're assigning the value. That's why ReSharper says the names are redundant.
Explicitly stating property names when you don't have to is personal preference; once you're familiar with the above convention I don't think it harms readability.
how does it know what the property names will be use to match to the db property class since they are passed by value
In a nutshell anonymous types are created on compile time. So the compiler resolves property names using expressions passed and in the result we have an anonymous class with declared readonly properties. You can check your IL in order to see that the assembly contains this type and properties are set explicitly.
what is best practice having the property names in or not
It depends on each person. I would recommend to choose a single way for your team and use the same ReSharper settings on each developer machine.

"To" vs "As" vs "Get" Method Prefixes

Does anyone know of any naming convention rules/guidelines that dictate when to use a "To" prefix (myVariable.ToList()), an "As" prefix (myVariable.AsEnumerable()), or a "Get" prefix (myVariable.GetHashCode())?
I assume there's no convention, so just use what fits best to what you're doing.
"To" creates something new/ converts it
"As" is just a "different view" on the same f.e. by using iterators
"Get" is a getter for everything else
My understanding/conventions:
"To" performs a conversion; A new object is created in memory, based on the data inherent in your source.
"As" performs a cast; The same reference passed in is returned behind the "mask" of a different type.
"Get" performs pretty much anything else that takes in a source and whose primary product is a transformed result. Gets can perform a calculation, return a child, retrieve data from a store, instantiate objects from a default state, etc. Not all such methods have to be named "Get", but most methods intended to calculate, instantiate, project, or otherwise transform, and then return the product as their primary purpose are "getters".
When myObj is not related to List, prefix "To" to convert.
When myObj is a subclass of Enumerable, prefix "As" to give it as Enumerable
When myObj is not related to List, but it composes / can compose List use "Get" prefix
If you're using Entity Framework for CRUD operations on a database, then using .ToList() will have your query be executed right there, as opposed to using AsEnumerable() which will use deferred execution until you actually try to access a record.
That's one that I thought of right off the top of my head.
As is a reinterpretation of existing data. AsEnumerable does nothing. It is implemented as return input;.
To implies a conversion.
Get does not imply any of the former.
You will find valid deviations from these rules. They are not set in stone.
I would say that To vs As has more to do with differences like class vs interface
i e you are saying AsEnumerable when you really want to return something that implements interface.
ToList on opposite returns new object which is representation of current state of current object, ie ToDictionary just another way of representing same data.
Third ones Get methods returns some properties of the object OR something about part of it's state and not the full state.

Categories

Resources