1

I'm using a .net script service which is called from client-side script, and it works very nicely.

only problem is- it generates a '__type' attribute for each of the returned objects, which I don't want or need.
I've seen a few posts about this over the web, and as far as I could tell, there are only 'workarounds' for this:

  • some people suggested hiding the parameter-less c'tor of the return type as 'internal protected',

  • others suggested not using the [ScriptMethod] tag, and instead JSONfy the result manually and return a string.

I'm wondering whether there is another, better, solution for this. and by the way- what is this attribute used for, anyway?
I'm enclosing the service method and the generated JSON.

method:

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json, UseHttpGet = true)]
public IEnumerable<EmployeePO> GetEmployeesForDepartment(int DepartmentId)
{

        return new AdministrationController().GetEmployeesForDepartment(DepartmentId);

}

JSON returned:

{"d":[{"__type":"Application.Controllers.PresentationObjects.EmployeePO","Positions":[{"__type":"Application.Controllers.PresentationObjects.PositionPO","Id":4,"Name":"Employee: 1test Position 1","IsPriority":false,"WarningThreshold":50,"CriticalThreshold":60,"CurrentWaitingTime":-1,"Passengers":[],"Qualifications":[...
John Saunders
  • 160,644
  • 26
  • 247
  • 397
J. Ed
  • 6,692
  • 4
  • 39
  • 55
  • Why do you care? Can't you just ignore it? – John Saunders Feb 13 '11 at 00:37
  • 1
    of course, but the whole point of using JSON is to have your objects as light as possible. That extra attribute is just extra weight on my objects. – J. Ed Feb 13 '11 at 07:45
  • @Groxx: I prefer to "dump a stack trace" in production. Helps find errors so they can be fixed instead of running buggy code in production. – John Saunders May 12 '11 at 01:15
  • @John: That's your choice, but it tends to expose you to side-channel attacks. Especially of note for .NET is the padding oracle attack from a while back, which is greatly helped by such a dump, and pretty much opens your entire system up to any action once it's completed. – Groxx May 12 '11 at 04:23
  • @Groxx: if you were referring to displaying a stack trace to the browser, then I misunderstood. I never do that. I do, however, log the full exception using ASP.NET Health Monitoring. And in that case, I don't see how __type relates. – John Saunders May 12 '11 at 04:35

4 Answers4

3

OK so I ended up taking the advice from Jhon Morrison, posted in the question @Kid linked to-
I defined all the parameter-less constructors on my returned classes as protected internal and that really did the trick.
In cases where I actually needed to create empty objects I created a Factory method, like so:

public class MyClass
    {
        public int Id { get; set; }
        /*...*/

        public MyClass(int id):
        {
            Id = id;
        }


        public static MyClass CreateNewZonePO()
        {
            return new MyClass();
        }

        //parameterless c'tor for serialization's sake
        //it's protected internal in order to avoid the "__type" attribute when returned from a web service. see http://stackoverflow.com/questions/4958443/net-script-web-services-type-attribute
        protected internal MyClass()
        {

        }
    }

@Kid's answer also worked, but it looked cleaner to me this way.

J. Ed
  • 6,692
  • 4
  • 39
  • 55
2

I have noticed that anonymous types returned as object do not produce the __Type attribute at all. I had returned some of my objects like this for different reasons and Javascript dont care, it loves anonymous types. So I suppose I will start converting many of the other types casting them down to the base object that all objects inherit from. The service layer will handle this because I like passing around strong types and don't want to convert it until the last minute. Does this casting take time? Probably. Is it worth it? Geez, I don't know. I agree tho, that this info should not be in there for security reasons. C'mon Microsoft.

Kid
  • 21
  • 2
  • this just might be the best possible solution. can you give an example for returning an anonymous type which contains the exact same fields as the POCO you're using? – J. Ed May 12 '11 at 20:49
  • I am messing around with it more today. I am not going to convert everything it will get to be so much more to create and maintain. There has got to be another way. I realized my answer was unclear, here is an example... Create an anonymous object that replicates your object then cast it to the type object and return it like this... object returnValue = (object) new { Property1=myObject.Property1, Property2=myObject.Property2 }; As you can see, it returns an object that was created from an anonymous object therefore there it does not exist in your namespace, its anonymous. – Kid May 13 '11 at 12:43
  • Could a method be written to automate this process? – Kid May 13 '11 at 12:52
  • 1
    OK I am using a combo of the above and stuff from this post... http://stackoverflow.com/questions/627356/how-to-not-serialize-the-type-property-on-json-objects – Kid May 13 '11 at 13:21
0

I did it a little different and for me a little cleaner. (I'm not trying to take away from the previous answer, just trying to add / reduce the amount of coding required.)

public class MyClass
{ 
    private MyClass(int id) { } //needs to have a constructor with at least one parameter passed to it. Update: looks like this is not needed. I still need to test this some more though.

    protected internal MyClass() { } //this actually drives the restriction on the JSON return of the __type attribute and is an overload constructor
}
JoeFletch
  • 3,820
  • 1
  • 27
  • 36
0

If you change the return type from IEnumerable<EmployeePO> to IEnumerable<Object>, the __type field won't be added to the JSON string.

Andrew Barber
  • 39,603
  • 20
  • 94
  • 123