ASP.NET 4 JSON DataContractJsonSerializer Lower Case - asp.net

I have a class with several properties all defined in sentence case:
Public Class Provider
Public Property ProviderName As String
End Class
I need to be able to pass instances of this through AJAX which I will then be using in JavaScript to add to an array, process etc. Currently I am using the DataContractJsonSerializer to serialize to JSON and return through an ASHX handler. It may just be me being picky, but I don't really like having sentence case properties in JavaScript, I would prefer them all to be lower case, to produce the following:
alert(myProvider.providername);
With the default DataContractJsonSerializer I simply cannot find a way to do this! With JSON.NET it would appear that it is a simple task, but unfortunately I can't introduce another dependency into this project - as much as I would like to.
Does anybody know of any way to override the format of keys that are generated?
The project is using ASP.NET Web Forms 4.0.
Thanks,
Chris.

It's possible to customize the DataMember attribute to use a lowercase name. Here's the syntax in C#, I assume in VB should be similar:
[DataMember(Name = "title")]
public string Title { get; set; }

Related

Does anyone know a good practice to use when developing for the system.directory services class?

I'm trying to create a data access later using System.DirectoryServices. I'd like to use the MVC 2 framework and have all my views be mostly strongly-typed. Does anyone know any good way to this?
For example I started creating a Group Entity:
public class Group
{
public string DistinguishedName { get; set; }
public string GroupName { get; set; }
}
And an abstract interface:
public interface IGroupRepository
{
List<Group> Groups { get; }
}
I am confused about developing the GroupRepository using the system.directory services. Connecting to a SQL database is easy there are examples everywhere but I have no been able to find any using the System.directory sevices in conjunction with a class using MVC. Has anyone tried to do something like this? Any great would be
If you're on .NET 3.5 (and if you use MVC 2, chances are good you are), you should check out the new System.DirectoryServices.AccountManagement namespace which brings you lots of strong .NET classes and types for many of the directory objects you're dealing with on a regular basis - no need to re-invent the wheel (yet again!).
Check out this great article in MSDN magazine on how to use this S.DS.AM namespace:
Managing Directory Security Principals in the .NET Framework 3.5
Update: for reasons I don't totally understand, the simple approach of using a UserPrincipal as a model for a ASP.NET MVC view doesn't work - it seems as if ASP.NET MVC cannot "find" any properties on that object.
So the approach would have to be to do something like this:
grab your UserPrincipal (or DirectoryEntry) from Active Directory
define a separate ViewModel - this is just a class that holds properties, like first name, last name and so forth
you can either fill that ViewModel class yourself, or you can grab some help like AutoMapper to make mapping from UserPrincipal (DirectoryEntry) to your ViewModel easier
then display (or edit) your ViewModel class in a standard ASP.NET MVC view
handle any possible updates by transferring any changes back from the ViewModel to the "proper" object and persisting that object
It's a bit more involved than I'd like it to be - but I quite honestly don't see how else you can do this otherwise.

DataAnnotations Automatic Handling of int is Causing a Roadblock

Summary: DataAnnotation's automatic handling of an "int?" is making me rethink using them at all.
Maybe I'm missing something and an easy fix but I can't get DataAnnotations to cooperate. I have a public property with my own custom validation attribute:
[MustBeNumeric(ErrorMessage = "Must be a number")]
public int? Weight { get; set; }
The point of the custom validation attribute is do a quick check to see if the input is numeric and display an appropriate error message. The problem is that when DataAnnotations tries to bind a string to the int? is automatically doesn't validate and displays a "The value 'asdf' is not valid for Weight."
For the life of me I can't get DataAnnotations to stop handling that so I can take care of it in my custom attribute.
This seems like it would be a popular scenario (to validate that the input in numeric) and I'm guessing there's an easy solution but I didn't find it anywhere.
Here's a workaround (as I wouldn't really call this a solution). Add a Messages.resx file inside the App_GlobalResources folder of your web application. Add the following resource inside:
Key: PropertyValueInvalid
Value: {0} Must be a number
In the Application_Start method of Global.asax add the following:
DefaultModelBinder.ResourceClassKey = "Messages";

Remove field in wsdl in Asp.net webservice

I'm generating dto classes with a template engine and would like to exclude some properties in an asmx webservice, what, if possible, is the best way to do this?
Ex:
[WebMethod]
public ProductPackages GetPackages()
{
ProductPackages packages = new ProductPackages();
packages.Packages.add(new PackageDTO());
return packages;
}
The PackageDTO contains some properties that's not relevant for this service.
But as the class can be regenerated any time i can't apply [XmlIgnore] to the fields.
So I'm looking for a way to apply a "exclude list" without touching the actual class.
Above is just an example, the template engine generates dto's for all tables in a given project, and I would like to be able to use them in services without needing to maintain a big bunch of nearly identical classes.
Just hit the same problem. You can exclude fields by marking them as internal.
public class Order
{
public double OrderPrice;
internal double ProfitMargin;
internal string TheTruthAboutThisCustomer;
}
If you don't want to return a field or property, then don't have it in the object you return! It's as simple as that.

Getting project web page names as an enumeration in asp.net

I know that in markup view Visual Studio will provide you with an enumeration of all the page names in your project (add an element and see what you get from Intellisense when specifying the ImageUrl attribute).
My question is: how do I get to that enumeration?
If that's not possible, what would be the best way in asp.net to get the names of your pages without having to hard code strings all over the place? E.g., I'd like to be able to do something like this:
Response.Redirect(PageNames.Default);
(Where PageNames is an enum of some sort)
Is this possible? Thanks in advance!
Here is one suggestion...
Define a class that includes the pages you want, either manually or by reading a Site Navigation file:
static class PageNames
{
public static string Default = "~/Default.aspx";
public static string Contact = "~/Contact.aspx";
public static string About = "~/About.aspx";
}
You can use the class by calling the property name:
Response.Redirect(PageNames.Default);
Another option, that I have looked at but not tried out yet (might next week tho'):
http://blog.devarchive.net/2008/01/auto-generate-strong-typed-navigation.html
Looks very cool, uses T4 templating to generate a strongly typed navigation hierarchy.

How to implement custom JSON serialization from ASP.NET web service?

What options are there for serialization when returning instances of custom classes from a WebService?
We have some classes with a number of child collection class properties as well as other properties that may or may not be set depending on usage. These objects are returned from an ASP.NET .asmx WebService decorated with the ScriptService attribute, so are serialized via JSON serialization when returned by the various WebMethods.
The problem is that the out of the box serialization returns all public properties, regardless of whether or not they are used, as well as returning class name and other information in a more verbose manner than would be desired if you wanted to limit the amount of traffic.
Currently, for the classes being returned we have added custom javascript converters that handle the JSON serializtion, and added them to the web.config as below:
<system.web.extensions>
<scripting>
<webServices>
<jsonSerialization>
<converters>
<add name="CustomClassConverter" type="Namespace.CustomClassConverter" />
</converters>
</jsonSerialization>
</webServices>
</scripting>
</system.web.extensions>
But this requires a custom converter for each class. Is there any other way to change the out of the box JSON serialization, either through extending the service, creating a custom serializer or the like?
Follow Up
#marxidad:
We are using the DataContractJsonSerializer class in other applications, however I have been unable to figure out how to apply it to these services. Here's an example of how the services are set-up:
[ScriptService]
public class MyService : System.Web.Services.WebService
{
[WebMethod]
public CustomClass GetCustomClassMethod
{
return new customClass();
}
}
The WebMethods are called by javascript and return data serialized in JSON. The only method we have been able to change the serialization is to use the javascript converters as referenced above?
Is there a way to tell the WebService to use a custom DataContractJsonSerializer? Whether it be by web.config configuration, decorating the service with attributes, etc.?
Update
Well, we couldn't find any way to switch the out of the box JavaScriptSerializer except for creating individual JavaScriptConverters as above.
What we did on that end to prevent having to create a separate converter was create a generic JavaScriptConverter. We added an empty interface to the classes we wanted handled and the SupportedTypes which is called on web-service start-up uses reflection to find any types that implement the interface kind of like this:
public override IEnumerable<Type> SupportedTypes
{
get
{
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
AssemblyBuilder dynamicAssemblyCheck = assembly as AssemblyBuilder;
if (dynamicAssemblyCheck == null)
{
foreach (Type type in assembly.GetExportedTypes())
{
if (typeof(ICustomClass).IsAssignableFrom(type))
{
yield return type;
}
}
}
}
}
}
The actual implementation is a bit different so that the type are cached, and we will likely refactor it to use custom attributes rather than an empty interface.
However with this, we ran into a slightly different problem when dealing with custom collections. These typically just extend a generic list, but the custom classes are used instead of the List<> itself because there is generally custom logic, sorting etc. in the collection classes.
The problem is that the Serialize method for a JavaScriptConverter returns a dictionary which is serialized into JSON as name value pairs with the associated type, whereas a list is returned as an array. So the collection classes could not be easily serialized using the converter. The solution for this was to just not include those types in the converter's SupportedTypes and they serialize perfectly as lists.
So, serialization works, but when you try to pass these objects the other way as a parameter for a web service call, the deserialization breaks, because they can't be the input is treated as a list of string/object dictionaries, which can't be converted to a list of whatever custom class the collection contains. The only way we could find to deal with this is to create a generic class that is a list of string/object dictionaries which then converts the list to the appropriate custom collection class, and then changing any web service parameters to use the generic class instead.
I'm sure there are tons of issues and violations of "best practices" here, but it gets the job done for us without creating a ton of custom converter classes.
If you don't use code-generated classes, you can decorate your properties with the ScriptIgnoreAttribute to tell the serializer to ignore certain properties. Xml serialization has a similar attribute.
Of course, you cannot use this approach if you want to return some properties of a class on one service method call and different properties of the same class on a different service method call. If you want to do that, return an anonymous type in the service method.
[WebMethod]
[ScriptMethod]
public object GimmieData()
{
var dalEntity = dal.GimmieEntity(); //However yours works...
return new
{
id = dalEntity.Id,
description = dalEntity.Desc
};
}
The serializer could care less about the type of the object you send to it, since it just turns it into text anyway.
I also believe that you could implement ISerializable on your data entity (as a partial class if you have code-gen'd data entities) to gain fine-grained control over the serialization process, but I haven't tried it.
I know this thread has been quiet for a while, but I thought I'd offer that if you override the SupportedTypes property of JavaScriptConverter in you custom converter, you can add the types that should use the converter. This could go into a config file if necessary. That way you wouldn't need a custom converter for each class.
I tried to create a generic converter but couldn't figure out how to identify it in the web.config. Would love to find out if anyone else has managed it.
I got the idea when trying to solve the above issue and stumbled on Nick Berardi's "Creating a more accurate JSON .NET Serializer" (google it).
Worked for me:)
Thanks to all.
If you're using .NET 3.x (or can), a WCF service is going to be your best bet.
You can selectively control which properties are serialized to the client with the [DataMember] attribute. WCF also allows more fine-grained control over the JSON serialization and deserialization, if you desire it.
This is a good example to get started: http://blogs.msdn.com/kaevans/archive/2007/09/04/using-wcf-json-linq-and-ajax-passing-complex-types-to-wcf-services-with-json-encoding.aspx
You can use the System.Runtime.Serialization.Json.DataContractJsonSerializer class in the System.ServiceModel.Web.dll assembly.
Don't quote me on this working for certain, but I believe this is what you are looking for.
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public XmlDocument GetXmlDocument()
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(_xmlString);
return xmlDoc;
}

Resources