Showing posts with label objects. Show all posts
Showing posts with label objects. Show all posts

Monday, March 26, 2012

Deserializing JSON objects manually - should I be doing this?

OK, I'm probably doing something horrendously wrong here, but here goes.

Following on from my battle with attempting to getembedded javascript to call an embedded web service I have got to a certain point and realised something may well be going wrong somewhere. I am intercepting calls to my web service usign a custom IHttpHandlerFactory. I am dealing with these calls using a custom IHttpHandler. I am talking back to the javascript by callingcontext.Response.Output.Write(...). (Correct me please if I'm doing anything wrong). Is there anyway to access the deserialized array of arguments passed to the web service? I can get the string passed from the javascript by analysingcontext.Request.InputStream.


So, given a"Person" class of:

class Person
{
string _name;

public string Name
{
get { return _name; }
set { _name = value; }
}
}


And aweb method of:

[WebMethod]
public Person ChangeName(Person p)
{
...
}


And ajavascript call of:

var person = new Person();
person.Name = "Josh";
MyWebServiceClass.ChangeName(person);


Thecontext.Request.InputStream is:

{"__type":"Person","Name":"Josh"}


If I try:

Person p = JavaScriptSerializer.DeserializeObject("{\"__type\":\"Person\",\"Name\":\"Josh\"}");

I get an argument null exception.


If I so much as change "__type" to "_type", I get a nice name-value collection.


If I change the string to remove the "__type" altogether and try:

Person p = JavaScriptSerializer.Deserialize<Person>("{\"Name\":\"Josh\"}");

I get a nicely deserializedPersonobject. But this involves messing with the InputStream, which I don't reckon I should have to be doing.

Any suggestions?

Cheers all,
Josh

Well, just as an update, I've discovered the way AJAX.NET deals with this deserialization is using a class called JavaScriptObjectDeserializer, which is now internal but I believe used to be public (seehttp://www.hanselman.com/blog/default.aspx?date=2006-07-07). I must be doing this wrong, can anyone give me any clues? Can I just return an instance of my web service in my HttpHandlerFactory somehow so I give it back to AJAX.NET to deal with I just "route" it to the right place? Please help!!!


I believe that this tutorial is a good resource for you:http://ajax.asp.net/docs/tutorials/ConsumingWebServicesWithAJAXTutorial.aspx

I didn't test it myself, but you could add a callback function to your code that invokes the web service, set the user context with the object you want to access it and then implement this callback function.

Hope this helps,

Maíra


Hi Maíra!

Thanks for the link! I'm not sure if this helps me out in my specific situation, but I might be wrong; I am not having the web service invoked under normal circumstances; I am intercepting a call (with my HttpHandler) for an "asmx" file that doesn't actually exist and trying to pass that call on the the relevent web service that is embedded within my dll. Maybe I don't understand what exactly is meant by setting the "user context", though - this sounds like it could be of help to me.

Thanks again,
Josh

Deserializing derived objects

Hello!

Maybe my question is rather stupid, but I'm just a newbie...

I have some classes derived from class DataObject, for example Account:

public

classAccount :DataObject {...}

and a [ScriptService()] - marked .asmx service with method

[

WebMethod( EnableSession =true )]publicDataObject AddObject(DataObject dataObject )

which passes this dataObject to another .svc service which writes it to database...

I call AddObject method throughSys.Net.WebServiceProxy.invoke(...), passing JavaScript object corresponding to Account class (I mean it has the same fields). If I set the parameter type in AddObject method to Account - everything works fine, it serializes and deserializes correct and passes further as an Account object. But if I try to set parameter type to DataObject - it looks like deserializer cuts all fields that are not declared in DataObject class and doesn't recognize derived object. The dataObject object in this method is pure DataObject, not Account.

I want to handle objects this way because actually I have now something about 10 classes and 10 such methods, and their number may increase. Writing all methods like AddAccount, AddUser, AddQuote and so on looks unhandy for me.

Is it possible for default JavaScriptSerializer to recognize derived objects? Or if I have to redefine it - how could I do that?

Thank you!

I faced a similar problem. The issue at hand is that the module that does the serialization/deserialization will look to the return types and parameters as cues for what it should serialize to / deserialize to , and it doesn't look deeper than that. I ended up doing a fairly hacky work-around to get the code in on time, but at some point I'm probably going to try and figure out a good solution.

A couple thoughts I had, neither of which are tried out. First, I'm aware that you can generate javascript types for nested types of the web service class (seehttp://ajax.asp.net/docs/mref/T_System_Web_Script_Services_GenerateScriptTypeAttribute.aspx) so that's an option, I suppose. Seems like not the best solution in our case, though, as what we're working with aren't logically nested types of the web service. I also considered writing a serializer module that can take the first param as a type argument so that, at the least, you could specify which concrete type you're sending upstream.instead of letting the module map only to the types in the webmethod params.


For XML Serialization (as used in classic 2.0 asmx web services) there is an attribute called XmlInclude which allows you to specify specializations of the actual return type. omly the ones you list with XmlInclude will be taken into account by the XmlSerializer.

I know the script service infrastructure hooks into the classic asmx stuff, but I have no idea if it looks at XmlInclude-s to. You might give it a try ...

-- Henkk

Wednesday, March 21, 2012

Define DropZones with DragOverlayExtender

Hi

I'm using the DragOverlayExtender to create a draggable UI (like live.com).
How can I define some fix drop-zones? So dragged objects should only drop there.

Tank you.

Hi,

I've just postedan article on my blog about drag&drop in Atlas, that includes an example of a draggable UI. Hope it helps.
Thx - this seems to be exactly what I was looking for!

But how can I add a control-section at runtime?

<control id="content1">
<behaviors>
<draggableListItem handle="content1Handle"
dataType="HTML" />
</behaviors>
</control>

I found that this works with

IScriptControl ctrl =
ScriptManager.GetCurrent(this).RegisterControl(myControl);

Then on ctrl there is a Method called RegisterBehaviour, but how can I use this. The method needs an IScriptBehavior-Implementation - so how can I use the draggableListItem-Behavior for this?
Hi,

Following the Atlas philosophy, the suggested approach (server-centric) would be that of creatingextenders for drop zones and draggable panels. Basically you have to derive a class fromExtenderControl and a class fromTargetControlProperties. Then, override theRenderScript() method of theExtenderControl class to render the Atlas markup.

Checkthis blog entry byNikhil Kotari orthis one from my Atlas blog, for some info about extenders.
Hi,

well, what I wrote above is not 100% correct, since anextender is supposed to extend an existing ASP.NET control or maybe acustom ASP.NET control. What you could do is build an Atlas-enabledserver control, rendering both the HTML and the Atlas markup.

Checkthis blog entry and look at the section "Support for Atlas-Enabled Server Controls" for some info.
Hey

So your second post is the way I tried... but I have still the problem that I mentioned. The number of controls that are draggable is not known at designtime, so I'd like to insert the DnD-behaviors for the different controls at runtime.

The follow method seems to be the one - but I don't know how to implement:
Microsoft.Web.Script.IScriptControl c =
ScriptManager.GetCurrent(this).RegisterControl(myControl);
c.RegisterBehavior(xxx);

So the 3x should be an IScriptBehavior-Implementation. In the declarative Way, I used
<control id="CVPart">
<behaviors>
<draggableListItem handle="CVPartTitle" dataType="HTML" />
</behaviors>
</control
So what do I have to do, to register this behavior (draggableListItem) at runtime.
OK... I found a quite simple solution... :-)

I've just created a new class that implements IScriptBehavior (and IScriptObject).
In the RenderScript-Method I just create the <draggableListItemhandle="myControl" type="HTML" /> with the ScriptTextWriter...

3 Lines of code... one day is over :-D
Thank you!

Hello! Could you please send me an example of your code?

Just to not waste the whole day for 3 lines of code ;)

Thank you!