PDA

View Full Version : Ext.Direct for ASP.NET MVC



Pages : [1] 2

elishnevsky
23 Jun 2009, 9:42 PM
Ext.Direct for ASP.NET MVC
Here is my implementation of Ext.Direct server-side stack for ASP.NET MVC 3 and 4.

Nov 12, 2012: The project has moves to GitHub.

Key features

* Easy setup
* Support for different types of parameters - simple types, complex types and arrays
* Form post values can be bound to multiple simple type parameters, a single complex type parameter (object) or a mix of both on the server
* Support for method aliases
* Exceptions with full stack trace and additional user-defined data for easy debugging
* Support for custom server-side events
* Support for named arguments (Ext JS 4.x)

The full source code is available here:

Ext.Direct for ASP.NET MVC on GitHub (https://github.com/elishnevsky/ext-direct-mvc)

Clone it or download the repository as zip file. You need to open the solutions in Visual Studio 2012 and allow NuGet to download missing packages before attempting to build it, as described in Compiling the source (https://github.com/elishnevsky/ext-direct-mvc#compiling-the-source) section in the README file.

Please read the README !!!

Any questions, comments, suggestions are welcome.

andycramb
24 Jun 2009, 1:42 PM
Very nice examples
I was thinking of converting my existing ExtJs MVc app to using Direct but I have not had time to look at using it
This is great to get me jump started

Questions
Does the DirectProvider class generate the DirectApi.js file and write it back to the response stream?
When does it do this? I noticed its cached if I add a new contoller will it automatically generate a new DirectApi.js file?

Does the router pick up all requests marked DirectRouter and then inspect the JSON and map the action to the controller and the method to the action?

elishnevsky
24 Jun 2009, 4:26 PM
Removed the comment. Its content was no longer valid in the latest version.

Razhick
25 Jun 2009, 3:56 AM
Very nice examples and thank you for sharing.

Just one comment; testing using FireFox 3.0.11 everything works but using IE 7, the tree and the grid panel do not show - Error: Object expected, Char: 13, Line 7506.

Thanks a lot!

elishnevsky
25 Jun 2009, 8:59 AM
Very nice examples and thank you for sharing.

Just one comment; testing using FireFox 3.0.11 everything works but using IE 7, the tree and the grid panel do not show - Error: Object expected, Char: 13, Line 7506.

Thanks a lot!

That's because I don't care about IE ;) But I fixed it anyways. Extra comma thing again, doh!

Just uploaded Ext.Direct.Mvc-0.2.zip. It requires you to make a small change in the configuration. Please change from this:

<section name="ext.direct" type="Ext.Direct.Mvc.DirectSectionHandler, Ext.Direct.Mvc"/>

To this:

<section name="ext.direct" type="Ext.Direct.Mvc.Configuration.DirectSection, Ext.Direct.Mvc"/>

Also added extra exception handling and moved all configuration related stuff to Ext.Direct.Mvc.Configuration namespace.

First post updated.

elishnevsky
27 Jun 2009, 6:19 PM
Uploaded version 0.3. Controller actions marked with DirectIgnoreAttribute (e.g. [DirectIgnore]) can now be executed as regular actions via the default route. Head post updated.

elishnevsky
29 Jun 2009, 6:39 PM
Uploaded version 0.4. You can now use [DirectIgnore] attribute to also mark classes (controllers) for ignore. This is useful if you need to create an abstract controller that itself uses DirectController as a base class.

mohaaron
30 Jun 2009, 9:16 AM
Nice work. I'm going to start building some test cases using this. Thanks for the examples and code.

franklt69
2 Jul 2009, 11:16 AM
Hi elishnevsky's , in your example you have only one view (index.aspx), is it the right approach? I mean, could you give more details about the view and javascript using this approach, what about if you have many aspx page in your app?

maybe is trivial but I am confused

regards
Frank

elishnevsky
2 Jul 2009, 11:29 AM
Hi elishnevsky's , in your example you have only one view (index.aspx), is it the right approach? I mean, could you give more details about the view and javascript using this approach, what about if you have many aspx page in your app?

maybe is trivial but I am confused

regards
Frank

When using Ext JS to develop a web application, it is usually the most common practice to only have one page and have all your markup generated by Ext JS. Therefore my current Ext.Direct implementation sort of follows this practice. However, you can still have more than one view and include the same API in all of them. You will just end up having some client-side methods in one view that you will never call, because they are meant to be used in another view.
As I wrote in one of my previous posts, I'm planning to support multiple providers in the future, just can't tell exactly when yet.

franklt69
4 Jul 2009, 5:23 AM
Thanks elishnevsky's, I am thinking if the JS files are larger (ext-all.js + manyfile.js) it could have problems, because the page delay in load, so is there some way to load the JS files on demand with this MVC approach?


Best regards
Frank

elishnevsky
4 Jul 2009, 7:28 AM
MVC doesn't not solve this problem. You can try search the forums for different solutions.

dke01
6 Jul 2009, 11:02 PM
Little more information:

Please also include in your instructions you have to add the following lines to your JS

Ext.ns('Ext.app');
Ext.Direct.addProvider(Ext.app.REMOTING_API);

For the newbies like me.

Also how do you go about setting the routerUrl when your in a sub folder (this is probably due to my lack of experience in MVC and routing) but if I have:

routerUrl="DirectRouter.ashx"
and then try so access a Script on MyDomain/Controler/Action then the 'DirectApi.ashx' get loaded correctly and when I view it I see "url": "DirectRouter.ashx"
This gives an 404 error because its looking for 'MyDomain/Controler/DirectRouter.ashx' and cannot find it because it is really in 'MyDomain/DirectRouter.ashx' I have tried adding '/' to my routerUrl but it give me errors.

For example if I also load your Demo project and go to localhost/home/Index it give an error

Thanks for the good work

elishnevsky
7 Jul 2009, 8:53 AM
dke01,
Thank you for the comment and bug report. Updated the head post. Please refer to the 'Usage' section there.

Also uploaded an updated version. Get it from the first post.

dke01
7 Jul 2009, 3:53 PM
Thank you for the super quick reply and fix these seems to work well.

The only other problem I seem to be having at the moment is out Action Links and website main menu (which is generated from a web.sitemap) since ALL request seem to be getting routed via your handeller it seems to be changing normal hyperlinks like

/Controller/Action to now be DirectRouter.ashx?control=xxx?action=yyy

Which then seems to break all the links? Not sure if there is someway to circumvent this behaviour? I do not have time to look at your source code and attempt to fix this myself at this stage but may later if I have time.

Thanks again for your assistance.

elishnevsky
7 Jul 2009, 6:24 PM
dke01,

Thank you very much for testing and reporting bugs! The issue you described should be fixed now.
BTW, it isn't true that all requests are routed via my handler. It's just that my custom route definitions were not complete. They are now, I hope :)

Please download updated version from the first post.

nightwatch
15 Jul 2009, 12:37 PM
Hi, I'm testing Ext.Direct MVC and have a problem. I configured everything as described here, built a controller and try to call the test method, but the DirectProvider has a problem with deserializing request body:

Newtonsoft.Json.JsonSerializationException was unhandled by user code
Message="Expected a JsonObjectContract or JsonDictionaryContract for type 'System.Collections.Generic.List`1[Ext.Direct.Mvc.DirectRequest]', got 'Newtonsoft.Json.Serialization.JsonArrayContract'."
Source="Newtonsoft.Json"
StackTrace:
at Newtonsoft.Json.Serialization.JsonSerializerReader.CreateObject(JsonReader reader, Type objectType, Object existingValue) in d:\Newtonsoft\Projects\Json\trunk\Src\Newtonsoft.Json\Serialization\JsonSerializerReader.cs:line 307
at Newtonsoft.Json.Serialization.JsonSerializerReader.CreateValue(JsonReader reader, Type objectType, Object existingValue, JsonConverter memberConverter) in d:\Newtonsoft\Projects\Json\trunk\Src\Newtonsoft.Json\Serialization\JsonSerializerReader.cs:line 164
at Newtonsoft.Json.Serialization.JsonSerializerReader.Deserialize(JsonReader reader, Type objectType) in d:\Newtonsoft\Projects\Json\trunk\Src\Newtonsoft.Json\Serialization\JsonSerializerReader.cs:line 94
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) in d:\Newtonsoft\Projects\Json\trunk\Src\Newtonsoft.Json\JsonSerializer.cs:line 344
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) in d:\Newtonsoft\Projects\Json\trunk\Src\Newtonsoft.Json\JsonConvert.cs:line 631
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) in d:\Newtonsoft\Projects\Json\trunk\Src\Newtonsoft.Json\JsonConvert.cs:line 595
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value) in d:\Newtonsoft\Projects\Json\trunk\Src\Newtonsoft.Json\JsonConvert.cs:line 552
at Ext.Direct.Mvc.DirectProvider.Execute(RequestContext requestContext) in C:\dev\ExtDirectMVC\source\Ext.Direct.Mvc\Ext.Direct.Mvc\DirectProvider.cs:line 119
at Ext.Direct.Mvc.DirectMvcHandler.ProcessRequest(HttpContextBase httpContext) in C:\dev\ExtDirectMVC\source\Ext.Direct.Mvc\Ext.Direct.Mvc\DirectMvcHandler.cs:line 51
at System.Web.Mvc.MvcHandler.ProcessRequest(HttpContext httpContext)
at System.Web.Mvc.MvcHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext httpContext)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

The method I'm trying to call:

public class DirectRPCController : Ext.Direct.Mvc.DirectController
{

public ActionResult Test1(string data)
{
return Direct(new {Ala = "nie ma kota" });
}
}


And my javascript invocation:


DirectRPC.Test1("ziutek");

Json that is sent to the server looks like so:

{\"action\":\"DirectRPC\",\"method\":\"Test1\",\"data\":[\"ziutek\"],\"type\":\"rpc\",\"tid\":2}


Something is wrong with JSon deserialization code in DirectProvider - this line fails:

var requests = JsonConvert.DeserializeObject<List<DirectRequest>>(json);


Can you help?

PS. I have some hint - probably the deserialization code expects an array of Json objects and the Json contains just a single object. When I tested a deserialize call with single DirectRequest, not a list:

JsonConvert.DeserializeObject<DirectRequest>(json)
it worked correctly and deserialized the Json as DirectRequest. So there's probably some mismatch between client-side and server-side code, either client-side should send a Json array, or the server should expect either an array or a single Json object.

Hint 2: I'm using the latest version of Newtonsoft.Json dll 3.5.0.0

elishnevsky
15 Jul 2009, 12:47 PM
I'm not sure why your JSON request contains backslashes in it. I guess it is what causes the crash. My JSON requests don't have backslashes:

{"action":"Employees","method":"Get","data":[0,10,"Name","ASC"],"type":"rpc","tid":2}

elishnevsky
15 Jul 2009, 12:59 PM
Ok, just tested you JSON string and backslashes have nothing to do with it.
The deserialization to List<DirectRequest> doesn't crash, it returns empty list (count = 0) and that's what I'm checking on the next line. It works fine for me. I really don't know what causes your crash.

I have added these 3 lines in the Index() action of HomeController in my TestApplication and they work fine:

string json = "{\"action\":\"DirectRPC\",\"method\":\"Test1\",\"data\":[\"ziutek\"],\"type\":\"rpc\",\"tid\":2}";
var listOfRequests = JsonConvert.DeserializeObject<List<DirectRequest>>(json);
var singleRequest = JsonConvert.DeserializeObject<DirectRequest>(json);

nightwatch
15 Jul 2009, 1:00 PM
Backslashes are there because I copied the json string from Visual Studio debugger and it escapes the string content in 'Quick View' window - the real Json doesn't contain them

elishnevsky
15 Jul 2009, 1:01 PM
Does my TestApplication work for you?

nightwatch
15 Jul 2009, 1:09 PM
No, it doesn't. This code:

string json = "{\"action\":\"DirectRPC\",\"method\":\"Test1\",\"data\":[\"ziutek\"],\"type\":\"rpc\",\"tid\":2}";
var listOfRequests = JsonConvert.DeserializeObject<List<DirectRequest>>(json);
var singleRequest = JsonConvert.DeserializeObject<DirectRequest>(json);


fails with the same exception as in my original post. So the problem is probably caused by different version of Newtonsoft.Json I'm using. Anyway, even if your version doesn't throw an exception, it doesn't deserialize DirectRequest correctly (returns an empty array instead), so the current DirectProvider will not work with this example. I'm using Newtonsoft.Json 3.5 beta 4 (because the rest of my application relies on this version).
R

elishnevsky
15 Jul 2009, 1:10 PM
Ok, newer version of Json .NET was released on July 6. It's 3.5 beta 4. My app is running on 3.5 beta 3. I guess the author of Json .NET changed the way deserializer works. I am going to download it later today and fix my app. Will post the update here.

nightwatch
15 Jul 2009, 1:12 PM
Thanks, hope the next version of Newtonsoft.Json will not break it again :)

elishnevsky
15 Jul 2009, 1:14 PM
Thanks, hope the next version of Newtonsoft.Json will not break it again :)

Yeah, let's hope so :) In the meantime you can use 3.5 beta 3.

elishnevsky
15 Jul 2009, 4:53 PM
Ok, newer version of Json .NET was released on July 6. It's 3.5 beta 4. My app is running on 3.5 beta 3. I guess the author of Json .NET changed the way deserializer works. I am going to download it later today and fix my app. Will post the update here.

Fixed. Please get the updated version from the first post.

nightwatch
16 Jul 2009, 12:16 AM
Great, I have tested it and my original problem is gone. However, I have found another issue to keep you busy:
I want to pass a json object directly to controller method, either as a JObject from Newtonsoft.Json library, or a dictionary - here are the examples:

public class DirectRPCController : Ext.Direct.Mvc.DirectController
{
public DirectResult Execute(JObject job)
{
return Direct("nie ma tu nic");
}

public DirectResult Execute2(Dictionary<string, object> job)
{
return Direct("nie ma tu nic");
}

public DirectResult Execute3(IDictionary job)
{
return Direct("nie ma tu nic");
}
}
The problem is none of the above methods gets the correct value of input parameter. Client side looks like this:

DirectRPC.Execute({'ala':'ma kota', 'kot':'ma 2 lata'});
DirectRPC.Execute2({'ala':'ma kota', 'kot':'ma 2 lata'});
DirectRPC.Execute3({'ala':'ma kota', 'kot':'ma 2 lata'});

And the JSON (ignore the backslashes):

"{\"action\":\"DirectRPC\",\"method\":\"Execute3\",\"data\":[{\"ala\":\"ma kota\",\"kot\":\"ma 2 lata\"}],\"type\":\"rpc\",\"tid\":2}"

Upon deserialization in DirectProvider the DirectRequest.Data field contains an object (exactly of type System.Object), so all the json fields are lost. And when the method invocation is done first method (Execute) gets an empty JObject, second method gets an empty dictionary and the third one gets null.
What is the correct method of passing any dictionary or any javascript object structure to a method?
Best regards,
Rafal

nightwatch
16 Jul 2009, 12:25 AM
Update: serialization doesn't work also for other custom object types, like:


public class Alice
{
public string ala { get; set; }
public string kot { get; set; }
}

public class DirectRPCController : Ext.Direct.Mvc.DirectController
{
public DirectResult Execute4(Alice job)
{
return Direct("nie ma tu nic");
}
}

If you invoke this method with the following js:

DirectRPC.Execute4({'ala':'ma kota', 'kot':'ma 2 lata'});

the 'job' parameter will be null on invocation

R

elishnevsky
16 Jul 2009, 6:35 AM
I am afraid there is nothing I can do about it. Currently Ext.Direct doesn't support passing object literals as arguments. Here's a quote from Ext.Direct Remoting Specification (http://extjs.com/products/extjs/direct.php):

Each transaction can contain

* action – The class to use
* method – The method to execute
* data – The arguments to be passed to the method – array (Ext.Direct will support named arguments in the future and thefore an object literal here)
* type - “rpc” for all remoting requests
* tid – Transaction ID to associate with this request. If there are multiple transactions in a single POST these will be different.

If you want to pass complex type object you have to pass it as a string and then manually transform it into whatever object you want on the server. Simply encode your object literal to a string using Ext.encode() and pass the result to your method call. For an example look how I do it in my test application (file: SampleTestPanel.js, method: onEchoPerson())

nightwatch
16 Jul 2009, 6:52 AM
Ow, that would be a serious limitation. But I understand the specification differently:
* data – The arguments to be passed to the method – array (Ext.Direct will support named arguments in the future and thefore an object literal here)

For me it means that Ext.Direct passes method arguments in an array and not in object literal - that's perfectly OK, I don't want to pass arguments by name. I just want to pass more complex object structures as method arguments, and there's nothing in spec that would suggest it's not possible (actually, handling just simple value types would defeat the whole purpose of Json-RPC).
And it actually does handle complex Json on client side - see my posts above and the Json string - it is delivered to the server, but the server-side code does not deserialize it properly. I think it could be greatly improved if your code used the type information from method parameters to deserialize Json to proper data types, not just System.Object which is useless.

Best regards
R

elishnevsky
16 Jul 2009, 7:03 AM
Let me have a think :) Although it might be very tricky and not worth the effort. I personally don't see a hude need in passing objects as objects, I am fine with passing them as strings. It the end, passing an object as a string and deserializing it to an object on the server yourself is pretty easy, and also you have full controll over how it is done.

nightwatch
16 Jul 2009, 7:07 AM
Let me have a think :) Although it might be very tricky and not worth the effort. I personally don't see a hude need in passing objects as objects, I am fine with passing them as strings. It the end, passing an object as a string and deserializing it to an object on the server yourself is pretty easy, and also you have full controll over how it is done.

But then, why did you bother writing all this sophisticated Ext.Direct.MVC library if you can pass everything in a JSon string and decode it manually on the server?

elishnevsky
16 Jul 2009, 7:24 AM
But then, why did you bother writing all this sophisticated Ext.Direct.MVC library if you can pass everything in a JSon string and decode it manually on the server?

Hmm.. I don't know how exactly to answer your question. If you are ready to throw away this library just because you can't pass complex types as objects, then go ahead, I'm not forcing anyone to use it :) Maybe you can find an easier way to generate API, parse and route your requests, do batching and so on... And don't forget, you can still use the good old Ext.Ajax.request().

nightwatch
16 Jul 2009, 9:37 AM
Hi, I'm sorry if my remarks seemed offensive, didn't mean it - I just wanted to give you some inspiration about future development. Without handling json objects this library is not very useful for me, but as I see all the other implementations of Ext.Direct for .Net listed on this forum have just the same problem (btw, they have very similar source code - a coincidence?). So maybe I'll try to modify your code to handle this case (rather a major refactor), or I'll roll something simple from scratch.
Best regards
R

elishnevsky
16 Jul 2009, 9:45 AM
No problem. You see, to convert an object literal passed with Direct request to a real object on the server, Convert.ChangeType() can be used, but then the class must implement IConvertable interface. If you know an easier way to convert Object to another complex type, I'll be glad to hear about it and can try and implement it in my solution. Meanwhile I'll do some research myself.

nightwatch
16 Jul 2009, 9:54 AM
The main problem is that information is lost in deserialization of DirectRequest. If the data array contains Json objects, they are all deserialized as System.Object and all their fields are ignored. This is because Json serializer doesn't know their actual type - it assumes System.Object because DirectRequest.Data is an array of System.Object. If you gave the Json serializer information about actual types of objects in that array it would handle the deserialization correctly. Now this would require getting type information from method parameters before deserialization of Data array, or deserializing everything as Newtonsoft.Json.JObject and later converting it into actual parameter types. I'll do some thinking as well about how to do that.

nightwatch
16 Jul 2009, 10:52 AM
To illustrate what I'm talking about, I have made some modifications to your source code to allow the library to handle complex Json types. I don't think it's a good implementation and probably it breaks many things that were working before, but at least handles some of my cases.
The modifications:
- added converter attribute to DirectRequest.Data
- implemented RequestDataConverter for custom deserialization of DirectRequest.Data
- modified DirectMethodInvoker so it converts JObject to appropriate method argument type
The implementation is dirty, my custom deserialization code probably will fail in many situations, but it correctly handles two of my test cases:
DirectRPCController.Execute2 and DirectRPCController.Execute4 (see the post above for details).
Hope you'll be able to incorporate this idea into your library (or prove it's wrong and offer something better)

Best regards
RG

elishnevsky
16 Jul 2009, 8:58 PM
Thanks, this looks pretty good to me! I followed your idea and added support for complex types. This will make it easier to pass simple DTOs around between server and client.

Get the updated version from the first post.

Please don't ask me to add support for even more complex types such as arrays or dictionaries, 'cause I'm not going to do it :D It's far more difficult and will result in a big hack for a little problem. Besides, this latest version with support for complex types should satisfy most of people's needs, if not all.

nightwatch
16 Jul 2009, 10:41 PM
Hi, I'm glad you liked it. BTW, dictionary support is already there - if the method parameter is a dictionary (not an IDictionary interface but dictionary class) the Json serializer will fill it with data from JObject. I'm not asking you to add array support, but you are small step away from it, besides it would be good for the sake of completeness. Maybe let's wait until someone needs it.

geewhizbang
17 Jul 2009, 12:31 PM
I have downloaded your project added the Ext.Direct.Mvc project to my Mvc Project.

I have done all of the code changes in Web.Config, the project compiles fine, and my existing ExtJS methods work in the way that a previous MVC example I found elsewhere showed me how to do. This is better than my previous two attempts that I eventually abandoned.

However, I can't tell from your project HOW you implement a method using the Ext.Direct, which I want to test to see if I like it.

A big source of my confusion is that I don't understand where DirectRouter.ashx is supposed to exist, and what is the format of a method in that if it does exist somewhere?

I have included my version of the project at box.net:

http://www.box.net/shared/1h9o0ks0vo

elishnevsky
17 Jul 2009, 12:48 PM
You don't have to create neither DirectRouter.ashx nor DirectApi.ashx. They are not physical files. These values are used by Ext.Direct.Mvc to define two routes - one to generate API, and one to route Direct requests. DirectHandler.ashx (or whatever value you used in web.config) simply defines URL to be used by Ext.Direct to make AJAX requests against.
Just follow the steps in the first post precisely, and you'll be fine.

geewhizbang
20 Jul 2009, 11:32 AM
I am starting to get a handle on this, but I still haven't set up my project correctly.

http://www.box.net/shared/1h9o0ks0vo

The project elishnevsky has setup works, but now I am trying to copy concepts from this page to another website, and I am missing something.

I need something simpler to start, so I have just deleted out most of the content except for a panel and a "Hello World" button.

I have deliberately used different namespaces because this forces me to understand where everything is coming from.

I suspect that I have some problems with referring to the correct objects on this line (in Site.Master

<%= Html.ActionLink("Direct", "DirectPage", "Direct")%></li>

It fails in the following code:

protectedoverridevoid ExecuteCore() {
if (ControllerContext.RouteData.RouteHandler isDirectMvcRouteHandler) {
this.ActionInvoker = newDirectMethodInvoker();
} elseif (IsDirectMethodCall()) {
thrownewInvalidOperationException("This controller action can only be executed by Ext.Direct.");
}
base.ExecuteCore();
}


This is the error I most often get:
A public action method 'DirectPage' could not be found on controller 'Ext.Direct.Mvc.DirectController'.


I have once gotten this error (with a prior edit of the code), but I haven't figured out how to duplicate it:


This controller action can only be executed by Ext.Direct

geewhizbang
20 Jul 2009, 3:57 PM
http://www.box.net/shared/ad841i4dal

This new file is now correctly implements "Hello World" on the Direct tab.

I was getting confused about namespace names, view names, and so on. Perhaps this example will help others since it is very simple.

I am now working on implementing the CustomerOrders tab using ext.direct.

elishnevsky
20 Jul 2009, 4:18 PM
As for your previous post, keep in mind, that every action in a controller, that inherits from DirectController, is considered a Direct method, unless marked with [DirectIgnore] attribute. Such controller actions should only be used by Ext.Direct and cannot be executed in any other way, except in a Direct request context.

As for your last post, I don't understand your confusion. Can you please describe your problem?

geewhizbang
20 Jul 2009, 10:58 PM
I am new to the MVC pattern as well as to ExtJS. So almost everything about this is unfamiliar. So I was getting confused between Ext.Direct actions, view names, controllers, especially since I was renaming everything on purpose so such confusions WOULD happen and I'd have to work them out.

I also had to rename the test project namespaces so I'd have more clarity while editing to know which project was the test bed and which was your reference code. I had to restore your original project from the downloaded zip file because I accidently overwrote it with some of my testbed code.

I have two more weeks of down time to get my head wrapped around this, and it appears to be a great way to implement my upcoming project which will be converting some very complex asp.net pages that were written very badly in highly repetitive ASP classic and were ported in the most work-intensive but intellectually lazy way possible to ASP.Net 2003 a long time ago.

I want to avoid intellectual laziness this time and do modern Web 2.0 coding. Part of that is becoming part of the open source community and ExtJS appears to be very robust and elegantly designed, so this looks like a great place to be.

I am reasonably good at Javascript, but the ExtJS style of defining things with functions inside functions, and internal complex nested arrays is not exactly the way I was used to building or using my objects. It is a very compact way of coding but it will take a few more days for me to start doing this with some confidence.

elishnevsky
21 Jul 2009, 9:23 AM
Well, all I can say is "good luck" :) There's many good starting points to learn Ext JS. Check out the links in my signature.
As for ASP.NET MVC, there's the official site (http://www.asp.net/mvc/) as well as some blogs, for example this one (http://weblogs.asp.net/scottgu/default.aspx) or this one (http://stephenwalther.com/blog/Default.aspx).

netski
22 Jul 2009, 5:11 PM
Hello elishnevsky,

Great contribution works well out of the box.

Was wondering, any support for unit testing? Or at a minimum the ability to call the methods directly for testing if they are not attributed with ignore?

Cheers,
Timothy

elishnevsky
22 Jul 2009, 5:31 PM
Hello elishnevsky,

Great contribution works well out of the box.

Was wondering, any support for unit testing? Or at a minimum the ability to call the methods directly for testing if they are not attributed with ignore?

Cheers,
Timothy

What you always can do is call the methods directly from the Firebug console, like so:

Test.AddNumbers(10, 33, function(result, response) {
console.info(result);
});

With regard to unit testing you can try something like JsUnit (http://www.jsunit.net), but I personally don't use it, so I can't tell how good or bad it is.

netski
23 Jul 2009, 4:42 AM
Thanks elishnevsky -- I was hoping to avoid using the console but hey ... it's better than nothing ;)

Again, cheers for the wicked job on the this contribution!

Cheers,
Timothy

netski
23 Jul 2009, 6:05 PM
Hello elishnevsky,

Was just wondering how you would deal with a form that has more than 25 fields to submit to an action, I don't want to have to write a server side action that has 25 parameters for each one.

Any recommendations?

Thanks again for your help, much appreciated :)

Cheers

elishnevsky
23 Jul 2009, 6:21 PM
Was just wondering how you would deal with a form that has more than 25 fields to submit to an action, I don't want to have to write a server side action that has 25 parameters for each one.

Your server side method can have a single complex type parameter and MVC will automatically create an instance of that type and initialize it with the values from the form. It will map fields names to the names of the properties of that class, so they have to be identical. Take a look at Form Test Panel example in the TestApplication (FormTestPanel.js and TestController.SaveForm method).

elishnevsky
24 Jul 2009, 11:29 AM
Uploaded new version 0.6.1. The changes are:

* Fixed: If cached DirectProvider API is flushed by IIS it is regenerated and cached again
* Removed: DirectProviderCache class

Please download it from the first post.

geewhizbang
24 Jul 2009, 2:10 PM
function ForumInit()
{
if (!KnowledgeBase.Forum.Init)
{
DirectRequest.GetForumList
(
function(result, response)
{
KnowledgeBase.Forum.Init = true;
KnowledgeBase.Forum.ForumList = result;
if (KnowledgeBase.Forum.ForumList != null && KnowledgeBase.Forum.ForumList.length > 0)
{
comboForum = new Ext.form.ComboBox
(
{
title: 'Select Forum',
store: KnowledgeBase.Forum.ForumList,
triggerAction: 'all',
autoWidth: true,
valueField: 'ForumID',
displayField: 'ForumName',
forceSelection:true,
renderTo: 'divForum_RR'
}
);
comboForum.addListener('select', SelectForum);

Ext.get("divForum_RR").innerHTML = KnowledgeBase.Forum.ForumList[0].toString();
AddBoxes(PageTabs.getComponent("ForumTab").body.dom);
}
}
, this);

}
}

I get back an object with multiple fields, but it contains some extra columns. The combo renders but the value says object object instead of the values.

elishnevsky
24 Jul 2009, 4:13 PM
You issue is not related to my implementation of Ext.Direct for MVC. As long as the data comes back from the server, it's not really my problem.
Nevertheless, what I can suggest is to check, if the data is in the required format according to the docs here (http://extjs.com/deploy/dev/docs/?class=Ext.form.ComboBox&member=store). If you still can't solve the problem please post your question in another forum and try to keep this thread only to discuss my implementation of Ext.Direct.
Thanks.

geewhizbang
25 Jul 2009, 3:51 PM
the direct request:

publicActionResult GetForumList()
{
List<ForumMember> f = kbForum.GetForumsByCategory(_catId);
if (f.Count == 0) f = null;
return Direct(f);
}


This is the clientside code I had to use to convert what I got back to a format the grid could use.


function ReformatResult(r, rowIdField)
{
var columns = [];
var dt = [];
var rowIdIndex = 0;
for (var col in r[0])
{
if (col == rowIdField) rowIdIndex = columns.length;
columns.push({name: col});
}
for (iRow=0; iRow< r.length; iRow++)
{
dr = [];
for (iCol=0; iCol< columns.length; iCol++)
{
dr[iCol] = r[iRow][columns[iCol].name];
}
dt[iRow] = dr;
}
var store = new Ext.data.ArrayStore({ fields: columns, idIndex: rowIdIndex })
store.loadData(dt);
return store;
}

I was expecting the Direct() function to convert the data into something that the controls expect, not to have to reformat it. Or am I putting the wrong type of object into the direct function?

Do I need to write my own converter instead of direct()?

geewhizbang
27 Jul 2009, 11:01 PM
Thanks elishnevsky for creating a good project example to learn both ExtJS and Ext.Direct.

My company already is committed to doing the next project in ExtJS, and the license fee is already in the budget.

I don't have the background yet to understand the technical benefits of Ext.Direct vs some other mechanism for ASP.Net.

Your code base was far more stable than anything else I downloaded. I have successfully extended it to do a simple grid that displays data retrieved from an SQL query.

I also appreciated that it contained the full source code.

But Hemal (my manager) wants to know what are the reasons for going this way, vs. using Asp.Net AJAX function calls or some less complex method to return JSON -formatted data back to the web pages.

About two thirds of the sample code for other MVC or ASP.Net ExtJS implementations I tried elsewhere didn't even compile. They were missing huge pieces of code or were based on beta releases of ASP.Net so the function signatures were all wrong.

My boss wants a better reason than the happy accident that your code was the example that was easiest to implement and modify. This may be precisely a good reason to go this way, but he is concerned that the code may have some large overhead in server resources, especially since I don't yet understand it very well.

Are there some advantages, such as cacheing requests that is provided by your code?

I am also somewhat concerned that the parser spit out JSON that had to be reformatted to be used by the grid control and drop down lists. While this can be done quickly on the clientside, it would be more elegant to send the data formatted in the ExtJS format in the first place.

I found this link for one person that is very enthusiastic about Ext.Direct and ExtJS but he doesn't get into enough specifics.

Are there any other links or info you can provide to lead me to a good technical decision?

http://erhanabay.com/2009/07/01/ext-direct-for-asp-net-mvc/

elishnevsky
28 Jul 2009, 6:54 AM
Thanks, I'm glad you liked it and it worked well for you.
My project works right out of the box because I think it is very important to do when you share your code with other people. It is compiled against the latest version of ASP.NET MVC.
Tell your boss not to be concerned. Ext.Direct is really just another RPC (http://www.google.com/search?q=RPC) mechanism, but for Ext JS. Before starting to write my implementation of Ext.Direct for MVC I studied the source code of ASP.NET MVC thoroughly. I didn't write my Ext.Direct implementation just to share with the community, I am actually using it in my projects too, and obvously it is in my best interests that it will be stable and reliable.
In terms of overhead, it needs to run reflection at least ones to generate the API off your code, and maybe more times when IIS decides to flush cache, that occasionally happens, but ASP.NET MVC from M$ runs reflection much more often :) With regard to actual requests, they puts as much overhead on the server as simple AJAX requests. As a matter of fact they are still simple AJAX requests, so there's nothing to worry about here. And there's no need to cache them, besides, I don't know how you cache a request. You could cache a response, but that's a totally different thing and entirely up to you and has nothing to do with Ext JS.

I am also somewhat concerned that the parser spit out JSON that had to be reformatted to be used by the grid control and drop down lists. While this can be done quickly on the clientside, it would be more elegant to send the data formatted in the ExtJS format in the first place.
I don't follow you here. In Ext JS you almost never need to reformat JSON response, especially when using it with grid, combo boxes, forms etc... You rely on a Store class to do it.

The benefits of Ext.Direct are:
* You can call your server-side method from the client as if they were written on the client.
* Ability to batch multiple requests and send them as one to the server.
* Using Ext.Direct for MVC you write you server-side methods and they are automatically exposed on the client.
* more in this blog post (http://extjs.com/blog/2009/05/13/introducing-ext-direct/).

geewhizbang
28 Jul 2009, 10:03 AM
To add to my previous post on this thread. I have tried to use direct request exactly like you did for your grid, but it creates an object but it never renders.



<div class="SD_Title">Forum Page</div>
<div id="divForumMain">
<div name="RR_forum" id="divForum">Test Box here</div>
</div>
<script type="text/javascript">

KnowledgeBase.gridForumList = Ext.extend
(
Ext.grid.GridPanel,
{
title: 'Forums',

frame: true,
viewConfig: { autoFill: true },
sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
stripeRows: false,
initComponent: function()
{
var ds = new Ext.data.DirectStore
(
{
directFn: DirectRequest.GetForumList,
fields:
[
{name: 'ForumID', type: 'string'},
{name: 'ForumName', type: 'string'},
{name: 'CreatedBy', type: 'string'},
{name: 'CreatedDate', type: 'date'},
{name: 'ForumType', type: 'string'},
{name: 'NumberOfPosts', type: 'int'},
{name: 'NumberOfThreads', type: 'int'},
{name: 'ForumCatId', type: 'int'},
{name: 'ModifiedBy', type: 'string'},
{name: 'ModifiedDate', type: 'date'}
],
remoteSort: false
}
);
var config =
{
store: ds,
columns:
[
{header: 'Forum Name', dataIndex: 'ForumName', sortable: true},
{header: 'Created By', dataIndex: 'CreatedBy', width:140, sortable: true},
{header: 'Created Date', dataIndex: 'CreatedDate', width: 90, xtype: 'datecolumn', format: 'M d, Y', sortable: true},
{header: 'Type', dataIndex:'ForumType', width:50, sortable: true},
{header: 'Posts', dataIndex:'NumberOfPosts', width:50, sortable: true},
{header: 'Threads', dataIndex:'NumberOfThreads', width:50, sortable: true},
{header: 'Category', dataIndex:'ForumCatId', width:100, sortable: true},
{header: 'Modified By', dataIndex:'ModifiedBy', width:140, sortable: true},
{header: 'Modified Date', dataIndex:'ModifiedDate', width: 90, xtype: 'datecolumn', format: 'M d, Y', sortable: true}
]
};
Ext.apply(this, Ext.apply(this.initialConfig, config));
KnowledgeBase.gridForumList.superclass.initComponent.apply(this, arguments);
},
afterRender: function()
{
this.getStore().load();
KnowledgeBase.gridForumList.superclass.afterRender.apply(this, arguments);
}
}
);
Ext.select('div[name^=RR_forum]').boxWrap();
Ext.reg('gridForumList', KnowledgeBase.gridForumList);

</script>


While this runs, but I have to use the function I previously posted to reformat the response.



function ForumInit()
{
DirectRequest.GetForumList
(
function(result, response)
{
Ext.select('div[name^=RR_forum]').boxWrap();

KnowledgeBase.Forum.Init = true;
if (KnowledgeBase.Forum.ForumList != null && KnowledgeBase.Forum.ForumList.length > 0)
{
KnowledgeBase.gridForumList = new Ext.grid.GridPanel
(
{
renderTo: 'divForum',
title: 'Forums',
frame: true,
autoFill: true,
stripeRows: false,
scroll: false,
autoHeight:true,
autoWidth:true,
sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
store: ReformatResult(result, "ForumID"),
columns:
[
{header: 'Forum Name', dataIndex: 'ForumName', sortable: true},
{header: 'Created By', dataIndex: 'CreatedBy', width:140, sortable: true},
{header: 'Created Date', dataIndex: 'CreatedDate', width: 90, xtype: 'datecolumn', format: 'M d, Y', sortable: true},
{header: 'Type', dataIndex:'ForumType', width:50, sortable: true},
{header: 'Posts', dataIndex:'NumberOfPosts', width:50, sortable: true},
{header: 'Threads', dataIndex:'NumberOfThreads', width:50, sortable: true},
{header: 'Category', dataIndex:'ForumCatId', width:100, sortable: true},
{header: 'Modified By', dataIndex:'ModifiedBy', width:140, sortable: true},
{header: 'Modified Date', dataIndex:'ModifiedDate', width: 90, xtype: 'datecolumn', format: 'M d, Y', sortable: true}
]
}
)
}
}
)
}
ForumInit();

elishnevsky
28 Jul 2009, 10:21 AM
I have tried to use direct request exactly like you did for your grid
Not exactly :) You don't need to reformat anything. The reason you don't see the data is that you have to set paramsAsHash:false or configure paramsOrder options on the DirectStore. Check the EmployeeGrid.js example in my test application.

geewhizbang
28 Jul 2009, 10:49 AM
This is a bit confusing as I don't have any parameters to pass. The direct function uses other context to determine which data to send.

Adding the following line (in bold):



directFn: DirectRequest.GetForumList,
paramsAsHash: false,


and still nothing happens. My breakpoint on the server side for the direct function never happens.

geewhizbang
28 Jul 2009, 3:42 PM
I posted this on general help, and someone says my method only creates the class, it doesn't actually render it. You code was using some other container to render the grid, and unfortunately the person that responded to my problem didn't mention HOW to get it to render.

elishnevsky
28 Jul 2009, 3:49 PM
Can you post here the response data, that comes back from the server after the call?

geewhizbang
28 Jul 2009, 5:19 PM
This is what comes back from the call ( I encoded "r" in the reformatResult() function below

[{"ForumID":5,"ForumName":"Autos","ForumType":0,"ForumCatID":0,"ForumOrder":0,"CreatedBy":"KBAdmin,KBAdmin","ModifiedBy":"","ModifiedDate":"1-01-01T00:00:00","CreatedDate":"2009-07-19T14:20:57","NumberOfThreads":2,"NumberOfPosts":3}]


This is what I used to change this into an array store that worked



function ReformatResult(r, rowIdField)
{
var columns = [];
var dt = [];
var rowIdIndex = 0;
for (var col in r[0])
{
if (col == rowIdField) rowIdIndex = columns.length;
columns.push({name: col});
}
for (iRow=0; iRow< r.length; iRow++)
{
dr = [];
for (iCol=0; iCol< columns.length; iCol++)
{
dr[iCol] = r[iRow][columns[iCol].name];
}
dt[iRow] = dr;
}
var store = new Ext.data.ArrayStore({ fields: columns, idIndex: rowIdIndex })
store.loadData(dt);
return store;
}

elishnevsky
28 Jul 2009, 5:27 PM
I don't understand. Your data looks ok. You should be able to use DirectStore just fine.

liaoqihua
29 Jul 2009, 1:58 AM
what's pitty, the down link was wrong ,could you share for me by email(philps_liao@hotmail.com), thanks.

elishnevsky
29 Jul 2009, 6:21 AM
The link works fine, just tested.

zihotki
29 Jul 2009, 8:46 AM
Greetings,

First of all, thanks a lot for your implementation of Ext.Direct for ASP.NET MVC!
I have few questions:
- Which license is this code under? Could you please include it in the code?
- And do you have some unit tests and a public repository? Are you planning to move this code to some repository (Google Code, Codeplex, etc)? That will be very helpful to submit patches and track bugs and whatever.

geewhizbang
29 Jul 2009, 12:51 PM
I don't understand. Your data looks ok. You should be able to use DirectStore just fine.

Perhaps the problem is that I am NOT using direct store in the code example. I was using the raw result directly, but that never worked, so I finally wrote the converter functiion to turn the raw result into a dataArray that did work.

I was used to using the raw results directly in ASP.Net Ajax, but then again I was working with my own objects so I built them to use whatever was coming back rather than using a conversion class like ExtJS

I have tried to stuff the result into a direct store, but the correct syntax has eluded me. I haven't succeeded at simplifying the grid in your example, since I haven't wrapped my head yet around Ext.Extend or class constructors yet. I'm perfectly happy to just create instances at this stage of my learning curve.

elishnevsky
29 Jul 2009, 1:08 PM
I finally wrote the converter functiion to turn the raw result into a dataArray that did work
This is a huge hack and you really shouldn't be doing this. If you like to work with raw data yourself, at least try to use JsonStore.

Not to offend you in any way, but to help you, I think that you should spend more time learning Ext JS without Ext.Direct, forget about it for now. Read FAQ, study API, analyze examples, see how people solve common problems etc.

Anyways, this is far off the original topic of this thread, so I would very much appreciate if we post here only to discuss my implementation of Ext.Direct for MVC.

geewhizbang
29 Jul 2009, 1:19 PM
All I am asking is for a clearer example on how to use the DirectStore object. Your current one is wrapped in some very elaborate distractions. I don't see how that is off topic.

elishnevsky
29 Jul 2009, 1:24 PM
You use DirectStore very similar to how you use JsonStore.
Here's a link to API docs: http://extjs.com/deploy/dev/docs/?class=Ext.data.DirectStore

You can also see how I use it in my test application.

elishnevsky
13 Aug 2009, 8:53 AM
Uploaded new version 0.6.2.

Added: Ability to specify converters and serialization settings when returing DirectResult from a direct method. Check the signatures of Direct() method in DirectController class


Get it from the first post as usual.

geewhizbang
20 Aug 2009, 3:58 PM
On many computers, this works perfectly. On others, it fails. On computers where it fails, it fails every time, and it works every time on the others. The browser type doesn't appear to make a difference on the computers where it fails. It fails in the same way on Firefox, IE6-8, Chrome, and probably others.

The code below runs when the tab is changed.
The last alert that appears before the failure is: alert("define panel")

It's hard to explain the computer-related consistency of the failures. It really does work only on some computers and not on others. If it doesn't workk in IE6 / IE7 / IE8 on a paticular computer, it also doesn't work on Firefox. I have talked to our network admin, and he says our corporate network is completely "flat", meaning that nothing is differently configured anywhere.

The other issue that I have just diagnosed is that the server side component DirectRequest.InitWiki doesn't happen on computers where the failure occurs.

On the same computer, several other direct requests run without errors. Most of these return less-complex objects, but otherwise isn't much different than this request. While there IS a pattern to this failure I don't see what could be causing it.

Line: 14639
Error: 'dom' is null or not an object

ServerSide code


publicActionResult InitWiki()
{
//code to get wikiList, which is a complex nested object
return Direct(wikiList);
}


ExtJS code where failure occurs:


if(this.el){
this.el = Ext.get(this.el);
if(this.allowDomMove !== false){
ct.dom.insertBefore(this.el.dom, position);
}
}


In the debugger, this.el.dom is definitely an object, but ct is null.

If I don't enter the debugger, I get a second error:
Line: 4324
Error: Could not complete the operation due to error 80020101.

After this error, moving to another tab works, but ExtJS appears to be broken in rendering any more new elements.



function OpenWiki(params)
{
if (typeof(KnowledgeBase.gridWiki) == "undefined")
{
alert("openWikiData");
KnowledgeBase.Wiki.data = new Ext.data.DirectStore
(
{
proxy: new Ext.data.DirectProxy
(
{
paramsAsHash: false,
directFn: DirectRequest.InitWiki
}
),
autoLoad: false,
directFn: DirectRequest.InitWiki,
paramsAsHash: false,
idProperty: 'WikiID',
fields:
[
{name: 'WikiID', type: 'int'},
{name: 'TemplateID', type: 'int'},
{name: 'PortalID', type: 'int'},
{name: 'PortalName', type: 'string'},
{name: 'SessionID', type: 'int'},
{name: 'ClientID', type: 'int'},
{name: 'Title', type: 'string'},
{name: 'Createdate', type: 'date'},
{name: 'Modifydate', type: 'date'},
{name: 'Viewdate', type: 'date'},
{name: 'ModifyUserID', type: 'int'},
{name: 'ModifyFirstName', type: 'string'},
{name: 'ModifyLastName', type: 'string'},
{name: 'Template', type: 'int'},
{name: 'CheckOut', type: 'int'},
{name: 'CheckOutUserID', type: 'int'},
{name: 'CheckOutFirstName', type: 'string'},
{name: 'CheckOutLastName', type: 'string'},
{name: 'CheckOutDate', type: 'date'},
{name: 'StatRateCount', type: 'int'},
{name: 'StatAveRating', type: 'int'},
{name: 'SttatHitCount', type: 'int'}
],
remoteSort: false,
listeners:
{
load: function()
{
KnowledgeBase.Wiki.data,
alert("data load");
}
}
}
);

alert("defineRenderers");
KnowledgeBase.Wiki.Renderers =
{
Wiki : function(value, p, r)
{
return String.format
(
'<div class="SD_CellTitleLink">{0}</a></div><div class="SD_CellText">{1}</div>',
value, 'Some description text goes here', r.data.WikiID
);
}
};
alert("define panel")
KnowledgeBase.Wiki.WikiGrid = new Ext.grid.GridPanel
(
{
renderTo: 'wikiHeaderBody',
frame: false,
stripeRows: false,
scroll: false,
autoHeight:true,
width: 800,
columnLines:true,
disableSelection: true,
trackMouseOver: false,
store: KnowledgeBase.Wiki.data,
columns:
[
{header: 'Tuan Wiki', id:'WikiID', width:400, dataIndex:'Title', renderer: KnowledgeBase.Wiki.Renderers.Wiki, sortable: false, menuDisabled:true},
{header: 'Posted Date', id:'Modifydate', width:200, dataIndex:'Viewdate', renderer: KnowledgeBase.Wiki.Renderers.Wiki, sortable: false, menuDisabled:true}
],
listeners:
{
render: function()
{
//this doesn't cause the problem, I have removed it and it still fails.
alert("displayer");
KnowledgeBase.Wiki.Displayer.onShow(KnowledgeBase.Wiki.WikiGrid);
}
}
}
);
alert("end define panel")
}
alert("load panel");
KnowledgeBase.Wiki.data.load();
}

elishnevsky
20 Aug 2009, 4:58 PM
I definitely couldn't know what causes that JavaScript error, and I am certain it is not related to Ext.Direct.
With regard to your problem with making Direct request, in your code above where you define DirectStore you create DirectProxy as well as set config options inherited from DirectProxy on the store itself. They are mutually exclusive, you don't need both of them, and perhaps that is what causes the problem with Direct request.
Check out the docs for DirectStore (http://extjs.com/deploy/dev/docs/?class=Ext.data.DirectStore), in particular where it says "*Note: Although they are not listed, this class inherits all of the config options of: ..."

elishnevsky
20 Aug 2009, 5:03 PM
Also, here's another weird piece of code:


load: function()
{
KnowledgeBase.Wiki.data,
alert("data load");
}

What exactly does it do? I think it fails here.

geewhizbang
20 Aug 2009, 11:16 PM
While the code you just pointed out would cause a crash, it was just an editing mistake in submitting this post. I had some very lengthy temporary debug code there that I didn't completely delete. My bad.

Since the post, I have now determined that it is a weird IIS issue with security permissions either on the code folders (the forum code that ALWAYS works is in a different folder) either for execute permissions or perhaps in log files this extremely raw new code is writing.

I haven't tracked it down yet, but oddly if the user is completely anonymous logged in as a user on their computer, the code works. If they login to our domain, IIS is probably trying to use their domain credentials instead of the ASP_Net account or web user, and it fails. This explains the failures across browsers, and the consistency of code always working / failing on the same computer. It also explains why the code on a separate code path using different folders is always working even on the computers that fail on the Wiki code.

As soon as I created a user account on one of the problem computers and logged on as that user rather than to a domain account, the problem went away on that machine.

So even if isn't quite an Ext.Direct problem, it is something that could come up again, so I will post the full solution tomorrow morning. It looks like it will be something simple, but the part that is crashing isn't my code so I don't know all of the resources it is using.

It looks like the conflict between proxy and directFn in my code example happened when some code using a grouping store got edited into something just using a normal grid. It does make sense now that they conflict. As I get more familiar with the ExtJS code patterns, the structures are getting easier write directly because I understand them rather than copying by rote, but I missed this. Thanks.

geewhizbang
25 Aug 2009, 11:32 AM
This request fails. Two different requests that don't have parameters work fine. If I restore Ext 3.0.0 javascript code files the request works fine.

When it fails, it fails to find a "json" object. I didn't write down the full error, so I will have to run the 3.0.1 code again to get a more accurate description of the issue.

The Ext 3.0.1 fixes some small layout issue so I would like to go back to using it if possible.

If this is not the right place to post this, I can now post on the registered user help since my company HAS bought the license, but I thought that this being related to Ext.Direct I could get some more specific help here.

client side code


KnowledgeBase.Forums.Forum.ThreadData = new Ext.data.DirectStore
(
{
directFn: DirectRequest.GetThreadsByForumId,
paramsAsHash: false,
paramOrder: 'ForumID',
baseParams: { ForumID: fid },
idProperty: 'ThreadID',
fields:
[
{name: 'ThreadID', type: 'int'},
{name: 'ThreadName', type: 'string'},
{name: 'ForumID', type: 'int'},
{name: 'CreatedBy', type: 'string'},
{name: 'ModifiedBy', type: 'string'},
{name: 'ModifiedDate', type: 'date'},
{name: 'CreatedDate', type: 'date'},
{name: 'NumberOfPosts', type: 'int'},
{name: 'NumberOfTags', type: 'int'}
],
remoteSort: false
}
);



in the direct view server side code.



public ActionResult GetThreadsByForumId(int ForumID)
{
List<ThreadMember> ft = kbForumThread.GetThreadByForum(ForumID);
return Direct(ft);
}

elishnevsky
25 Aug 2009, 11:40 AM
I've been having problems with 3.0.1 too. It's a little buggy. Don't use it. As a premium member you have access to SVN, try getting the source code from there and run your app. My app is currently running agains the latest SVN, and I'm not having any problems.

ostenieverson
27 Aug 2009, 1:39 PM
I can open a ux.MetaTabForm using Ext.Direct for ASP.NET MVC?
thanks!

geewhizbang
28 Aug 2009, 1:14 PM
I've been having problems with 3.0.1 too. It's a little buggy. Don't use it. As a premium member you have access to SVN, try getting the source code from there and run your app. My app is currently running agains the latest SVN, and I'm not having any problems.

I may not know what I am doing with the SVN. I can download the latest "trunk" items, but the other items fail with a permission error.

I have no idea which branch you are using successfully. I did notice that some layout bugs were fixed in 3.0.1 which is why I wanted to try it.

The trunk items only compile if I use the -d switch, and they so far they are even buggier than the 3.0.1 build. They also create core files with somewhat different names and file locations than in the released build.

canxss
2 Sep 2009, 1:09 AM
Hi,

I just want to get your detailed opinion about, while using ASP.NET MVC, what is the real benefit of using Ext.Direct compared to using simple AJAX in Ext JS. Because I don't have any problems or shortcomings while using ASP.NET MVC with Ext JS through AJAX calls and wondering whether I'm missing something.

I've read about Ext.Direct and your posts; although I couldn't run your TestApplication since I'm using ASP.NET MVC 2.0, I've checked out the code and pretty much understood what was going, but couldn't decide whether I need it or not.

In this post (http://extjs.com/forum/showthread.php?p=365118#post365118) you have briefly written the benefits of Ext.Direct as:


You can call your server-side method from the client as if they were written on the client.



Ability to batch multiple requests and send them as one to the server.



Using Ext.Direct for MVC you write you server-side methods and they are automatically exposed on the client.

But other than gaining the ability to batch multiple requests I don't see any real benefit. Since ASP.NET MVC enables us to use URL's easily on client-side and Ext JS AJAX call and processing is pretty simple, I didn't need to expose my server-side methods on client-side. But Ext.Direct seems mostly about that. And it also brings the disadvantage of getting to tied to Ext JS on the server-side.

So as a user of ASP.NET MVC with only Ext JS and with Ext.Direct, can you explain what did you really gain by using Ext.Direct? Did you get any performance improvement, vs? Are there other things that I'm missing?

Thanks in advance

elishnevsky
2 Sep 2009, 7:39 AM
Hi canxss,

Basically for me there's two obvious benefits of Ext.Direct.

Firstly, one of the key ways to improve performance of a web application one should never forget is to try and minimize the number of HTTP requests made to the server, therefore I think that the ability of Ext.Direct to batch multiple requests into one is a really really good thing and shouldn't be undervalued. For example in my project I have situations when I have to make 3 or more calls to the server from different UI components. With standard AJAX it would be 3 or more separate HTTP requests, with Ext.Direct it's only one.

Secondly, I just like way of calling server-side methods with Ext.Direct as if they were regular JavaScript functions. Although I didn't have any problems with making regular AJAX requests before, I find the new way a bit easier and more intuitive.

canxss
2 Sep 2009, 1:36 PM
Thanks for the reply. You're right about minimizing number of requests but other than that I'm OK with the old way. Until I hit bottleneck about performance in this subject, I don't think that I will be migrating to Ext.Direct.

Thanks again for the explanation.

rjett
8 Sep 2009, 12:56 PM
Are there any advantages to using this MVC project over a regular .Net Web Application with Ext.Direct if your app is a single page desktop like application and does not involve multiple pages?

maxigroovy
9 Sep 2009, 6:01 AM
Hi, I'm working on a proof-of-concept to demonstrate ExtJs to the rest of the company.

Paging in datagrids is a no-go here, so I looked at http://www.ext-livegrid.com Ext.ux.Livegrid.
Looks very good, with jsonstore. I also have it working with ASP.Net MVC (my favorite!).

Is it possible to use this livegrid with DirectStore? Or do I have to port the BufferedStore to DirectStore instead of JsonStore.

Could you give me a lead?

elishnevsky
9 Sep 2009, 6:10 AM
Hi, I'm working on a proof-of-concept to demonstrate ExtJs to the rest of the company.

Paging in datagrids is a no-go here, so I looked at http://www.ext-livegrid.com Ext.ux.Livegrid.
Looks very good, with jsonstore. I also have it working with ASP.Net MVC (my favorite!).

Is it possible to use this livegrid with DirectStore? Or do I have to port the BufferedStore to DirectStore instead of JsonStore.

Could you give me a lead?

I'm sorry, I haven't played around with LiveGrid. You are welcome to try it with DirectStore and my implementation of Ext.Direct for ASP.NET MVC and let me know how it went.

Olli
10 Sep 2009, 2:34 AM
Like 'zihotki (http://www.extjs.com/forum/member.php?u=60919)' in message #67 I'd like to know about the licensing of this nice piece of code. Can I freely use this in a commercial product?

geewhizbang
10 Sep 2009, 6:36 AM
Hi canxss,

Basically for me there's two obvious benefits of Ext.Direct.

Firstly, one of the key ways to improve performance of a web application one should never forget is to try and minimize the number of HTTP requests made to the server, therefore I think that the ability of Ext.Direct to batch multiple requests into one is a really really good thing and shouldn't be undervalued. For example in my project I have situations when I have to make 3 or more calls to the server from different UI components. With standard AJAX it would be 3 or more separate HTTP requests, with Ext.Direct it's only one.

Secondly, I just like way of calling server-side methods with Ext.Direct as if they were regular JavaScript functions. Although I didn't have any problems with making regular AJAX requests before, I find the new way a bit easier and more intuitive.

I've found it very easy to write requests that return a lot of different data at the same time, but they are still single requests. The batching together is hardcoded on the server. This is fine when I need a lot of different things at once, but when I need to update only one of the items, I either have to write a separate handler or send back a lot of unnecessary data.

The one thing I like is how easy and flexible it is to use a jsonReader handler for each item in the data.

This serverside batching could be done with conventional AJAX, too, so I don't think what I'm doing is what you're talking about here.

If I understand you correctly, you have a method of batching several requests together in one direct request. If so, can you explain this further?

elishnevsky
10 Sep 2009, 7:37 AM
Like 'zihotki (http://www.extjs.com/forum/member.php?u=60919)' in message #67 I'd like to know about the licensing of this nice piece of code. Can I freely use this in a commercial product?

I haven't looked into this whole licensing thing. I probably should. Anyways, it will most likely be distributed under GPL or MIT license. For now just use it.

elishnevsky
10 Sep 2009, 7:40 AM
If I understand you correctly, you have a method of batching several requests together in one direct request. If so, can you explain this further?

Take a look at my TestApplication, in the top right panel there's a button, that makes four different Direct calls that are batched into one HTTP request.

geewhizbang
22 Sep 2009, 10:14 AM
I have some requests that never return. I'm using the paging controller, on the server side the data is returned, but the clientside never finishes.

I suspect that it is a timeout issue, because the requests that don't work are randomly distributed, but all the requests that don't work are larger in size.

There is a way to add to the direct request timeout in 3.0.2 but I don't know where this is set. It has to be really low right now, because the requests that don't work are not very large at all, they are just bigger than the others.

geewhizbang
25 Sep 2009, 3:55 PM
I finally figured out why some request never return.

They were a bit huger than I expected because the server was returning all attachments that had been uploaded along with a page content.

I guess that is the downside of handing a complex object off to Direct() parser. Deeply nested inside one of the objects, one of these were too big.

elishnevsky
6 Oct 2009, 10:24 AM
** Important update. Please read. **

Ext.Direct for ASP.NET MVC v0.6.3 is uploaded.

In previous versions all dates were serialized using Json.NET's JavaScriptDateTimeConverter by default unless another converter is specified by a developer.

In this version a new dateFormat configuration attribute is introduced that allows you to specify what DateTime serialization format to use by default. Supported values are "Iso" and "JavaScript" to use Json.NET's IsoDateTimeConverter or JavaScriptDateTimeConverter respectively. If this attribute is not set in your application's config file, or contains value other than supported, then all dates will be serialized using the default Json.NET's serialization format which is the same as the one used by Microsoft. "\/Date(1198908717056)\/"

If you are upgrading from an older version you will most likely have to add the new dateFormat config attribute to your application's web.config file since the default serialization format of dates has changed in this version.

Please refer to the first post for the updated version of Ext.Direct.Mvc.

kriz
9 Oct 2009, 12:10 AM
I can't download this file from the author's link,can some one send it to my email: kenkrizzard@gmail.com ?

I'll very appreciate you help.

jcsarda
11 Oct 2009, 7:20 PM
I have a recreation of your test application working fine displaying records from your "Employees" table. I've created and tested my data context, so it should be working fine but I keep getting the following error...


Newtonsoft.Json.JsonSerializationException was unhandled by user code
Message="Self referencing loop"
Source="Newtonsoft.Json"
StackTrace:
at Newtonsoft.Json.Serialization.JsonSerializerWriter.CheckForCircularReference(Object value, Nullable`1 referenceLoopHandling)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.WriteMemberInfoProperty(JsonWriter writer, Object value, JsonProperty property)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.SerializeValue(JsonWriter writer, Object value, JsonConverter memberConverter)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.SerializeList(JsonWriter writer, IList values, JsonArrayContract contract)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.SerializeValue(JsonWriter writer, Object value, JsonConverter memberConverter)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.WriteMemberInfoProperty(JsonWriter writer, Object value, JsonProperty property)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.SerializeValue(JsonWriter writer, Object value, JsonConverter memberConverter)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.WriteMemberInfoProperty(JsonWriter writer, Object value, JsonProperty property)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.SerializeValue(JsonWriter writer, Object value, JsonConverter memberConverter)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.SerializeList(JsonWriter writer, IList values, JsonArrayContract contract)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.SerializeEnumerable(JsonWriter writer, IEnumerable values, JsonArrayContract contract)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.SerializeValue(JsonWriter writer, Object value, JsonConverter memberConverter)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.WriteMemberInfoProperty(JsonWriter writer, Object value, JsonProperty property)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.SerializeValue(JsonWriter writer, Object value, JsonConverter memberConverter)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.WriteMemberInfoProperty(JsonWriter writer, Object value, JsonProperty property)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.SerializeValue(JsonWriter writer, Object value, JsonConverter memberConverter)
at Newtonsoft.Json.Serialization.JsonSerializerWriter.Serialize(JsonWriter jsonWriter, Object value)
at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value)
at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value)
at Newtonsoft.Json.JsonSerializer.Serialize(TextWriter textWriter, Object value)
at Ext.Direct.Mvc.DirectResult.ExecuteResult(ControllerContext context) in C:\Documents and Settings\Administrator\My Documents\Visual Studio 2008\Projects\iNote\Ext.Direct.Mvc\Ext.Direct.Mvc\DirectResult.cs:line 71
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass11.<InvokeActionResultWithFilters>b__e()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
InnerException:


Has anybody gotten this error before? I'm sure it's something small... I'm a little new to both ASP.net MVC and Ext.js...

Anyways, thanks ahead of time for any help you can give me.

aritchie
12 Oct 2009, 5:43 AM
The JSON serializer has no concept of what it can and cannot serialize (unless specified). It looks like you may have some lazy loading objects that is causing this (child -> parent, parent -> children, etc). My suggestion is to flatten out your objects to DTO's instead of sending a raw business object. Look at something like AutoMapper to make your life easy for this.

jcsarda
12 Oct 2009, 3:12 PM
My model designer includes a bunch of extra code in my data context that would include relationship values to another table. Is there a way to exclude my one-to-many relationship (using LinqToSql) from my IQueryable object before I hand it over to result["data"]?

Here's my controller code:



SchcommDataContext _db = new SchcommDataContext();

public ActionResult Get(int start, int limit, string sort, string dir)
{

var schcommList = _db.Schcomms
.OrderBy(sort + " " + dir)
.Skip(start)
.Take(limit);

var result = new
{
total = _db.Schcomms.Count(),
data = schcommList // This value must contain information about my model associations that doesn't serialize properly
};

return Direct(result);
}

elishnevsky
13 Oct 2009, 11:17 AM
Ext.Direct for ASP.NET MVC v0.6.4 is uploaded. Please see the first post for download link.

Latest changes:
* Added: small adjustment for integration with the Ext Designer

If you're currently using v0.6.3 you don't have to upgrade.

isit.gd
14 Oct 2009, 5:22 AM
Hi

I want to be able to send down method names as properties on objects - i basically want to send an object which is the colmodel. each of the colmodel items has a renderer method in it:



{header: 'Name', dataIndex: 'Name', sortable: true, renderer: renderers.defaultRenderer }


i omit the quotes to send it as an object using a JsonConverter:



public class JavascriptMethodConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}

public override object ReadJson(JsonReader reader, Type objectType, JsonSerializer serializer)
{
throw new NotImplementedException();
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteRaw((string)value);
}
}


which gets added to the c# property like:



[JsonConverter(typeof(JavascriptMethodConverter))]
public virtual string Renderer { get; set; }


i keep getting an error saying it would result in invalid js whenever this is included.

this seems like a standard use case to me - is there anything i'm doing wrong?

cheers

w://

geewhizbang
20 Oct 2009, 4:42 PM
ExtJS code to do post submit:


f.submit
(
{
success: function(form, action)
{
debugger;
if (action.result.Success)
{
if (action.result.Tags != null)
{
var newTags = action.result.Tags;
for (var iTag = 0; iTag < newTags.length; iTag++)
{
var TagData = kbForum.ThreadView.Tags[params.ThreadId];
var newTags = action.result.Tags;
if (Ext.isDefined(TagData.TagIdIndex[newTagId]))
{
TagData[TagData.TagIdIndex[newTagId]] = newTags[iTag];
}
else
{
TagData.TagIdIndex[newTags[iTag].TagID] = TagData.length;
TagData.TagNameIndex[newTags[iTag].TagName] = TagData.length;
TagData.push(newTags[iTag]);
}
}
}
if (Ext.isDefined(kbForum.EditorParams.onSave)) kbForum.EditorParams.onSave(action.result);
kbForum.CloseEditor();
}
},
failure: function(form, action)
{
debugger;
//arrives here with a "server" failure result.
//the data is actually returned correctly, everything works.
}
}
);

Serverside code



[FormHandler]
[ValidateInput(false)]
public ActionResult SavePost()
{
string Title = Request.Form["PostTitle"];
string PostBody = Request.Form["PostBody"];
string Tags = Request.Form["Tags"].ToLower();
Dictionary<string, string> start = null;
List<CommunityTagMember> UpdatedTags = null;
int PostId = -1;
int PageSize = Utility.FixNullInt(Request.Form["PageSize"],5);
bool bSuccess = true;
int ThreadId = Utility.FixNullInt(Request.Form["ThreadId"], -1);

//snip – a whole bunch of code here, all of which runs just fine. It may
//be a lot of code, but I doubt that it is timing out.
var result = new
{
Success = bSuccess,
Tags = UpdatedTags,
PostId = PostId,
Start = start
};
// the code returns all of the way to here, but it isn't possible
// to follow this into the Direct() function without reconfiguring
// the project
return Direct(result);
}

aritchie
21 Oct 2009, 4:30 AM
You are returning "Success" not "success". It is a case sensitive check

isit.gd
22 Oct 2009, 1:47 AM
Sometimes i add a new method which returns
Direct in a controiller which inherits from
DirectController and the api at DriectApi.ashx never updates?

is there something i should be doing?

i've restarted the web and all that.

very good implementation however :) - i'm a big fan.

w://

maxigroovy
22 Oct 2009, 3:47 AM
Great tool.
I got it working with the LiveGrid store (based the Bufferstore on the DirectStore).

I wanted to save changed value in the store through a JsonWriter to the update api of the directstore (bufferedstore).
When I saved 1 item, everything was okay. But when I wanted to save more than one changed record from the store I got an array.
JArray was not supported.

I made an implementation but I'm really not sure if it is up to your standard, for me it works in my proof of concept. But it's not yet in production state. So if anyone has any comments, improvements or what ever, feel free.

I created a .patch file (with usage of subversion) against the 0.6.4 version.



Index: DirectMethodInvoker.cs
===================================================================
--- DirectMethodInvoker.cs (revision 4)
+++ DirectMethodInvoker.cs (working copy)
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
+using System.Reflection;
using System.Web.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@@ -23,10 +24,33 @@
string key = parameterDescriptors[i].ParameterName;
object rawValue = data[i];

- if (rawValue is JObject && parameterDescriptors[i].ParameterType != typeof(JObject)) {
- rawValue = JsonConvert.DeserializeObject(rawValue.ToString(), parameterDescriptors[i].ParameterType);
+ if (rawValue is List<object> && parameterDescriptors[i].ParameterType.BaseType == typeof(Array))
+ {
+ List<object> tempRawArray = rawValue as List<object>;
+ for( int j = 0; j < tempRawArray.Count; j++)
+ {
+ //If is array then get the type of the non array type
+ if (tempRawArray[j] is JObject && parameterDescriptors[i].ParameterType != typeof(JObject))
+ {
+ Assembly assembly = Assembly.GetAssembly(parameterDescriptors[i].ParameterType);
+ Type type = assembly.GetType(parameterDescriptors[i].ParameterType.FullName.Replace("[]",""));
+ tempRawArray[j] = JsonConvert.DeserializeObject(tempRawArray[j].ToString(), type);
+ }
+ }
+ rawValue = tempRawArray.ToArray();
}
+ else if (rawValue is JObject && parameterDescriptors[i].ParameterType != typeof(JObject))
+ {
+ Type type = parameterDescriptors[i].ParameterType;
+ if (type.BaseType == typeof(Array))
+ {
+ Assembly assembly = Assembly.GetAssembly(type);
+ type = assembly.GetType(parameterDescriptors[i].ParameterType.FullName.Replace("[]",""));
+ }
+ rawValue = JsonConvert.DeserializeObject(rawValue.ToString(), type);
+ }

+
string attemptedValue = Convert.ToString(rawValue, invariantCulture);
valueProvider.Add(key, new ValueProviderResult(rawValue, attemptedValue, invariantCulture));
}
Index: RequestDataConverter.cs
===================================================================
--- RequestDataConverter.cs (revision 4)
+++ RequestDataConverter.cs (working copy)
@@ -13,12 +13,34 @@

if (!dataArray.HasValues) return null;

- foreach (JToken dataItem in dataArray) {
- if (dataItem is JObject) {
+ foreach (JToken dataItem in dataArray)
+ {
+ if (dataItem is JObject)
+ {
data.Add(dataItem);
- } else if (dataItem is JValue) {
+ }
+ else if (dataItem is JValue)
+ {
data.Add((dataItem as JValue).Value);
- } else {
+ }
+ else if (dataItem is JArray)
+ {
+ List<object> listObjects = new List<object>();
+ foreach (JToken arrayDataItem in (dataItem as JArray))
+ {
+ if (arrayDataItem is JObject)
+ {
+ listObjects.Add(arrayDataItem);
+ }
+ else if (arrayDataItem is JValue)
+ {
+ listObjects.Add((arrayDataItem as JValue).Value);
+ }
+ }
+ data.Add(listObjects);
+ }
+ else
+ {
throw new ArgumentException("Arguments of this type are not supported.");
}
}


Now I can have an update action like this, supporting arrays.

[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Update(int[] ids, WebModelContainerStatus[] records)
{
if (Request.IsAjaxRequest())
{

maxigroovy
22 Oct 2009, 4:09 AM
I've got a question.
How to return if the update/ create / etc succeeded or failed?

I tried (in the action-method of the controller):


var result = new {
success = false
};
return Direct(result);


But don't know how to handle the response in ExtJs.

elishnevsky
22 Oct 2009, 6:21 AM
Sometimes i add a new method which returns
Direct in a controiller which inherits from
DirectController and the api at DriectApi.ashx never updates?

is there something i should be doing?

i've restarted the web and all that.

very good implementation however :) - i'm a big fan.

w://

Make sure your method on the server is a true controller action, i.e. its return type is ActionResult, otherwise the API generator will not pick it up. Can't think of another reason. Post your controller code here, I'll take a look.

elishnevsky
22 Oct 2009, 6:42 AM
maxigroovy

1. I'll take a look at how you implemented arrays later, too busy right now. But thanks!

2. With regard to your second comment, I honestly don't know :) I've never had to do anything like this. Anyhow, it's not directly related to my implementation of Ext.Direct, so you might want to start a new thread in the general Ext.Direct forums.

maxigroovy
25 Oct 2009, 11:49 PM
And ofcourse it's better to use:



Type type = parameterDescriptors[i].ParameterType.GetElementType();


instead of the string replacement thing:


Assembly assembly = Assembly.GetAssembly(parameterDescriptors[i].ParameterType);
Type type = assembly.GetType(parameterDescriptors[i].ParameterType.FullName.Replace("[]",""));


For handling the serialization of arrays.

isit.gd
26 Oct 2009, 11:45 AM
i really need to figure out how to do this - can anyone help?





Hi

I want to be able to send down method names as properties on objects - i basically want to send an object which is the colmodel. each of the colmodel items has a renderer method in it:



{header: 'Name', dataIndex: 'Name', sortable: true, renderer: renderers.defaultRenderer }
i omit the quotes to send it as an object using a JsonConverter:



public class JavascriptMethodConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return true;
}

public override object ReadJson(JsonReader reader, Type objectType, JsonSerializer serializer)
{
throw new NotImplementedException();
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteRaw((string)value);
}
}
which gets added to the c# property like:



[JsonConverter(typeof(JavascriptMethodConverter))]
public virtual string Renderer { get; set; }
i keep getting an error saying it would result in invalid js whenever this is included.

this seems like a standard use case to me - is there anything i'm doing wrong?

cheers

w://

kriz
1 Nov 2009, 9:30 PM
Can someone make a rs mirror?I can't download this file.Thks.

Ankai
4 Nov 2009, 9:16 PM
Hi!
At first, thanks for your work!

I need some advice or sample of using your implementation with polling provider, of course if you already have something specially for this? Now I'm creating new polling provider and it repetitively makes post requests to the action.

elishnevsky
5 Nov 2009, 7:12 AM
Hi!
At first, thanks for your work!

I need some advice or sample of using your implementation with polling provider, of course if you already have something specially for this? Now I'm creating new polling provider and it repetitively makes post requests to the action.

Polling provider doesn't require any server-side stack implementation. Check out this sample. (http://www.extjs.com/deploy/dev/examples/direct/direct.php)

isit.gd
9 Nov 2009, 3:19 AM
hi

i need to return a download of an excel doc from a controller method.
the scenario is that if the store is refreshed with an export flag, instead of returning json of the data i need it to return an excel doc instead - is that possible wiht this?

cheers

w://

elishnevsky
9 Nov 2009, 6:40 AM
hi

i need to return a download of an excel doc from a controller method.
the scenario is that if the store is refreshed with an export flag, instead of returning json of the data i need it to return an excel doc instead - is that possible wiht this?

cheers

w://

No. Do it separately.

Dave.Sanders
13 Nov 2009, 11:17 AM
Hey there, I've been using (and modifying) the traditional ASP.Net router for a while now, but am doing a new MVC project so I grabbed your code. One struggle I had, who's resolution might be useful to others, and one suggestion:

1. Struggle: I kept getting errors talking about how 'WriteJson' is not implemented in Ext.Direct.Mvc.RequestDataConverter. So, nothing was getting deserialized when I passed it up to the server. BUT, the test app included in the zip worked fine. Turns out that my Newtonsoft.Json was a 3.5 BETA, not the version that is being used by Direct.Mvc or in the test app. So, when it went to serialize, some changes between my version and your version of Newtonsoft caused epic failure. Easy to fix: if you are referencing the Newtonsoft.Json DLL in your project before hand - make sure you get up to date with the version that this code is based on.

2. Suggestion: It would be nice if the router would complain if the number of parameters sent in on the request don't match what the controller action accepts. I was fighting a "WTF?" bug today and it was because I had one extra parameter in my call. So, Ext.Direct was trying to assign my callback to a variable - not very helpful. :)

Probably more to come as I dig into it, but nice job!

elishnevsky
13 Nov 2009, 8:40 PM
Hi Dave,

1. Like any software that is compiled with a third party dll, my implementation of Ext.Direct for MVC is compiled with a specific version of Json.NET library and hence I cannot guarantee that it will work with a different version. This is why I include Json.NET dll in the bin folder together with my dll. In the next post I will announce the release of the next version of Ext.Direct.Mvc which is compiled with the very latest version of Json.NET. Please check it out.

2. As a matter of fact the router does complain about it - an exception of type DirectException is thrown and a direct response with type 'exception' is returned to the client. In my applications I always add the following code:

Ext.Direct.on('exception', function(e) {
if (window.console) console.error(e, e.message);
});
And of course I always have firebug open :)

elishnevsky
13 Nov 2009, 8:53 PM
Uploaded new version Ext.Direct.Mvc v0.7.

Latest changes:

* Added: support for passing one-dimensional arrays of simple as well as complex types
* Misc: compiled with Json.NET 3.5 Release 5 released on Sat Oct 10 2009 at 3:00 AM

Please test and report bugs.

To download see the first post (http://www.extjs.com/forum/showthread.php?p=347906#post347906) of this thread.

P.S. Thanks to maxigroovy for help with arrays.

Dave.Sanders
16 Nov 2009, 7:08 AM
On number of params not matching, I will test again - my js side is in flux and I might have missed it.

Speaking of error handling, I have a simple suggestion to add an optional param of Data to DirectException. This would be any object the user wants to pass to the front-end. I need this because I pass forward some extra info on the exception so that the user can make a comment on what they were doing to give me some extra debugging info.

It's a very simple addition for a (imho) lot of benefit. I've included the updated class below. You also need to make changes to DirectResponse, which I've included snippets of too.

DirectException

using System;

namespace Ext.Direct.Mvc
{
public class DirectException : ApplicationException
{
public object Data {get; set;}

public DirectException() { }

public DirectException(string message)
: base(message) { }

public DirectException(string message, object Data) : base(message) {
this.Data = Data;
}

public DirectException(string message, Exception innerException)
: base(message, innerException) { }

public DirectException(string message, Exception innerException, object Data) : base(message, innerException)
{
this.Data = Data;
}
}
}


DirectResponse:



public DirectResponse(DirectRequest request, DirectException exception)
: this(request) {
this.Type = ResponseExceptionType;
this.ExceptionMessage = exception.Message;
this.Where = String.Format("{0}.{1}", request.Action, request.Method);
this.Data = exception.Data;
}


and


[JsonProperty("data", NullValueHandling = NullValueHandling.Ignore)]
public object Data
{
get;
set;
}

elishnevsky
16 Nov 2009, 8:44 AM
In fact I did think about doing this but was stopped by the Ext.Direct Remoting Specifications (http://www.extjs.com/products/extjs/direct.php) that says the following:

If an exception occurs on the server-side the router should also return the following error information when the router is in debugging mode.

* type – 'exception'
* message – Message which helps the developer identify what error occurred on the server-side
* where – Message which tells the developer where the error occurred on the server-side.

This exception handling within the router should have the ability to be turned on or off. This exception information should never be sent back to the client in a production environment because of security concerns.

Exceptions are meant for server-side exceptions. Not application level errors.

In my implementation I tried to follow the spec how I understand it, although I am not sure if I understand it correctly.

For dealing with application level errors you can always catch exceptions in your controller action, build some custom error object, return it as if it was a regular data object and handle it properly on the client. Something like this:

public ActionResult MyAction() {
try {
// you main action logic here, such as data retrieval etc.
return Direct (data);
} catch (Exception ex) {
var errorObj = new {
success = false,
error = "You specific error message here...",
data = some_additional_data_object
};
return Direct(errorObj);
}
}

To check for server-side application exceptions on the client globally you could do something similar to this:

Ext.Direct.on('event', function(e, prov) {
var r = e.result;
if (r.type == 'rpc' && r.success && r.success == false) {
alert(r.error);
}
});
Perhaps additional logic is needed. Haven't tested myself. I don't have global server-side error handling on the client in my applications.

Dave.Sanders
16 Nov 2009, 8:56 AM
Well, I think it should be there, they should at least specify an optional data element. I personally think an optional, non-default data attribute wouldn't kill anything. Its helpful if you need more data than just where and message.

The reason I need it to come across as an exception is because then I can easily bind an event to it via the Ext.Direct.on("exception"). This way all exceptions go to the same place in my JS code.

I missed that Exception already has a data object, so its even easier. Here are the real changes that would need to happen - no changes to DirectRequestException needed.

DirectResponse:


public DirectResponse(DirectRequest request, Exception exception)
: this(request) {
this.Type = ResponseExceptionType;
this.ExceptionMessage = exception.Message;
this.Where = String.Format("{0}.{1}", request.Action, request.Method);
this.Data = exception.Data;
}

DirectProvider - change the catch in ExecuteRequest to catch on all exceptions - not just DirectRequestExceptions.


} catch (Exception exception) {

Then Data is a dictionary on your exception to add data to. What I do on the server side is have all of my controllers inherit from a common class, then catch OnException to alter the error data on the way out. Works well.

If you don't decide to include this because of their spec, then that's fine. I'll just fork my own - but I figured it might be useful to someone else.

elishnevsky
16 Nov 2009, 11:02 AM
I don't think that catching ALL exceptions in DirectProvider is a good idea. I prefer application level exceptions to bubble up to a controller action from any layer.

Perhaps I should have made it more clear, that DirectException is a public class and you can throw an exception of this type from anywhere in your code by simply doing

throw new DirectException(errorMsg);
DirectException class inherits Data property from ApplicationException class, so if you want to set it, you can do it:

throw new DirectException(errorMsg) {
Data = myData
};
Mind that type of Data property is IDictionary, so it can't just be any object.

I guess I should revisit error handling and provide an easier way to deal with exceptions. Let me have a think ;)

Dave.Sanders
16 Nov 2009, 11:39 AM
I can probably do it either way - because I'm catching all errors in a common controller class and altering them before sending them along. I could probably manage it so that I change them over to DirectExceptions.

However, the reason I want to catch on ALL errors is that, typically, the user would get a 500 page if a server error occurs. With a full AJAX app, these requests could just "disappear" from the user's point of view. (you see it in firebug just fine, but the user would see nothing) By having ALL exceptions get sent through, I can show the user that their attempt failed and collect more information.

D

Dave.Sanders
17 Nov 2009, 4:00 PM
Another suggestion:

Below are some changes to the RequestDataConvertor that will allow it to pass in arrays from the JS back to the methods. Arrays get converted into a List<object> type. There might be an easy way to cast this List<object> to a List<int> or a List<string> inside the Direct library, but I haven't taken a stab at it yet.


internal class RequestDataConverter : JsonConverter
{
public override object ReadJson(JsonReader reader, Type objectType, JsonSerializer serializer) {
var data = new List<object>();
var dataArray = JToken.ReadFrom(reader);

if (!dataArray.HasValues) return null;

foreach (JToken dataItem in dataArray) {
if (dataItem is JObject) {
data.Add(dataItem);
} else if (dataItem is JValue) {
data.Add((dataItem as JValue).Value);
} else if (dataItem is JArray) {
data.Add(ConvertJArray(dataItem as JArray));
} else {
throw new ArgumentException("Arguments of this type are not supported.");
}
}

return data.ToArray();
}

private List<object> ConvertJArray(JArray item)
{
List<object> output = new List<object>();
foreach (JToken dataItem in item.AsJEnumerable())
{
if (dataItem is JObject)
{
output.Add(dataItem);
} else if (dataItem is JValue)
{
output.Add((dataItem as JValue).Value);
}
else if (dataItem is JArray)
{
output.Add(this.ConvertJArray(dataItem as JArray));
}
else
{
throw new ArgumentException("Arguments of this type are not supported.");
}
}
return output;
}
public override bool CanConvert(Type objectType) {
return true;
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
throw new NotImplementedException();
}
}

elishnevsky
17 Nov 2009, 6:29 PM
Passing one-dimensional arrays from JS to the methods on the server is already supported in version 0.7. What you have added is support for multi-dimensional arrays, but it isn't complete. Similar changes have to be made to DirectMethodInvoker class. But do you think it's worth the effort? Personally I don't. I mean, it is such an extreme use case, that I don't think anyone will ever need it. Besides, if you find yourself passing multi-dimensional arrays, chances are you're doing something wrong and should revisit the code.


There might be an easy way to cast this List<object> to a List<int> or a List<string>

There is no way in C# to simply cast List of one type to List of another type, it doesn't work. It can only be done to each individual item in a loop and requires an additional List of target type.

Dave.Sanders
17 Nov 2009, 8:57 PM
First, what other changes? This code is working fine afaik, my arrays are making it to the backend just fine.

Second, apologies, I didn't look in .7 yet, mainly because I've been moving ahead with my development and had already forked for the error data requirement. I will take a look.

Third, what effort? This took about 10 minutes and was running. I expected to be able to send an array of values back from some custom front end code, your .6 code didn't support it and instead threw errors, so I added it.

Fourth, I don't have a case for multidimensional arrays either, but I also haven't written every app that will ever be needed. It's a part of json, and as a developer using the library I would at the minimum be confused why I can't send valid json through. And again it's basically zero work to implement with json.net, just break out a loop and it can be arrays all the way down if someone needs it. (actually array stores use md arrays so it's not entirely out of the realm of possibilty that someone, at some time, may need one too,)

Finally re the list coversion, no there isn't a simple one line way to do it, but there is a call that will call out to other functions for the conversion, that could likely use reflection to properly cast the list. I might figure it out at some point, but since I don't need it right this second, it's not high on my list. It, again, was merely a suggestion of another helper to expand the library and make it more user friendly.

Anyway sorry about not checking 0.7, I'll just keep my suggestions and code to myself. Thanks for the base code, I'll just add on what I need from here since I apparently have such amazingly custom needs.

elishnevsky
18 Nov 2009, 7:51 AM
v0.7 is doing everything you need including passing arrays ;) Except global exception handling that you asked for earlier. I will be releasing v0.7.0.1 soon with a few bug fixes and optimizations.

elishnevsky
24 Nov 2009, 10:34 PM
Ext.Direct.Mvc v0.8 is released.

I have decided to bump the version number to 0.8 because of the number of changes.
The download link is in the first post of this thread (http://www.extjs.com/forum/showthread.php?p=347906#post347906).

Changes:
* Added: All exceptions now return to the client as a direct response with type
"exception" so they can be handled globally by listenening to the "exception"
event.
* Added: New boolean configuration option called "debug" (optional, default to
false). When an exception occures on the server and this option is set to
true, the exception response contains a property called "where" with full
stack trace. This option should never be set to true in production
environment because of security concerns.
* Exception response can also contain a property called "exceptionData" with
additional user-defined information about the exception. It is set from
Exception.Data. To read about Exception.Data and how to set it see
http://msdn.microsoft.com/en-us/library/system.exception.data.aspx
* Changed: Direct() method signatures. Converters are now passed as params
array as opposed to List<JsonConverter> as it was done before.
* Added: Easy way to return a custom server-side events to the client. To do
that simply return the result of one of the DirectEvent() overloaded methods
from you action and listen to your event on the client as described in the
documentation to Ext.Direct class in "Server side events" section:
http://www.extjs.com/deploy/dev/docs/?class=Ext.Direct
* Removed: DirectException class.
* Misc: Bug fixes, better code organization.


Important!
Ext.Direct.Mvc is now licensed under the terms of the GNU Lesser General Public License version 3. A copy of the license can be found in the copying.txt and copying_lesser.txt files included in the distribution. A few people asked for it so here you go.

@Dave.Sanders
I was thinking a lot about your suggestions regarding exception handling and came to a conclusion that it makes total sense in an AJAX app, so I went ahead and implemented everything you asked for. The reason I chose the name "exceptionData" for the property that contains additional data about the exception is because Ext.Direct treats "data" property in the same way as the "result" property, i.e. as a valid returned data. I find it odd, but it is the fact. Anyways, thanks for your suggestions.

veenvliet.morion
25 Nov 2009, 4:37 AM
Great work.
I haven't had the time to test the new 0.8 version. But I think it's a great step forwards.

I have another request (or is it already implemented?).
Would it be possible to use gzip if possible to let IIS gzip the generated Javascript dynamicly?

Ofcourse only when gzip is possible. To be checked in the field Request.Headers["Accept-Encoding"].



HttpResponse Response = HttpContext.Current.Response;

string AcceptEncoding = HttpContext.Current.Request.Headers["Accept-Encoding"];
if (AcceptEncoding.Contains("gzip"))
{
Response.Filter = new System.IO.Compression.GZipStream(Response.Filter,
System.IO.Compression.CompressionMode.Compress);
Response.AppendHeader("Content-Encoding", "gzip");
}
else
{
Response.Filter = new System.IO.Compression.DeflateStream(Response.Filter,
System.IO.Compression.CompressionMode.Compress);
Response.AppendHeader("Content-Encoding", "deflate");
}


Another idea. Would it be possible to give the direct proxyclasses in javascript a namespace?
I have a



PumpsController: DirectController
{
//Action
ActionResult GetById(int id)
{
return Direct(data);
}
}


In Javascript this will can be called by:


Pumps.Get(id, new function(response)...);


I try to have everything programmed in ExtJS in useful namespaces.
Would it be possible to set a global namespace in the config and/ or set a namespace for a controller through an attribute class?



Morion.Controllers.Product.Pumps.Get(id, new function(response)...);


Just an idea, let me know what you think.

elishnevsky
25 Nov 2009, 11:43 AM
Hi veenvliet.morion,

Thanks for the ideas. I will think about gziping. I do like the idea of being able to overwrite method names, I'll see what I can do about it.

Regarding the namespaces, however, Ext.Direct supports only one namespace for all your direct actions. It creates client-side stubs from a API configuration object of a very strict structure, and there is nothing I can do about it. In my implementation you specify the namespace in the web.config.

veenvliet.morion
26 Nov 2009, 12:26 AM
Hi,

Thanks for your reaction (by the way, this is my business/ premium account. In private I'm maxigroovy :) )

The Gzip is only a matter of adding the header to the response. IIS will take care of the rest.

Renaming methods can also be a bless when having the same method name with different arguments (like you can change the webmethod name in a webservice with the same purpose).

You mean it can be done set the namespace in the web.config?


<ext.direct providerName="Morion.REMOTING_API" apiUrl="DirectApi.ashx" routerUrl="DirectRouter.ashx" assembly="TESTClient" dateFormat="JavaScript"/>

elishnevsky
26 Nov 2009, 1:34 PM
Hi,
You mean it can be done set the namespace in the web.config?


<ext.direct providerName="Morion.REMOTING_API" apiUrl="DirectApi.ashx" routerUrl="DirectRouter.ashx" assembly="TESTClient" dateFormat="JavaScript"/>


Absolutely. Check out the first post of this thread. Configuration section in particular.

veenvliet.morion
27 Nov 2009, 12:07 AM
ouch, totally missed that one.
Thanks!

elishnevsky
3 Dec 2009, 11:09 AM
Ext.Direct.Mvc v0.8.1 is released.

The download link is in the first post of this thread (http://www.extjs.com/forum/showthread.php?p=347906#post347906).

Changes:
* Remove: Interception of every exception introduced in v0.8.0 (was a bad idea).
* Added: DirectHandleErrorAttribute class which can be used to mark a whole
controller or an individual action with a [DirectHandleError] attribute to
intercept all exceptions and return a direct response of type "exception"
that contains the information about the exception.
* Added: DirectException class for throwing custom exceptions that will always
return to the client as a direct response of type "exception".
* Added: Suport for ActionNameAttribute. If an action is marked with this
attribute, then the specified name will be used when generating API and for
routing direct requests. Make sure that you use the name specified in this
attribute when calling the method from your JS code.
* Added: New overloaded methods in DirectController. Check out DirectForm().
* Renamed: exceptionData to errorData.
* Fixed: Serialization of DirectResponse in file upload mode.
* Misc: Other minor fixes and code optimizations.

I have also removed the Ext JS source from the test application and instead linked the scripts from cachefly.net. The package is now much smaller.

Thanks to the .NET expert and my colleague aritchie (http://www.extjs.com/forum/member.php?u=19083) for pointing out the issues with catching all exceptions.

elishnevsky
4 Dec 2009, 10:50 PM
Uploaded Ext.Direct.Mvc v0.8.2.

See the first post of this thread (http://www.extjs.com/forum/showthread.php?p=347906#post347906) for the download link.

Changes:
* Fixed: Binding DateTime, Enum, Guid and nullable types.
* Misc: Lots of unnecessary code was removed.

sergeime
5 Dec 2009, 5:43 PM
It seems with latest I have problems with passing GUID strings into server-side code. Earlier with version 7 I was able to invoke controller methods that had Guid parameters - now it is broken.
Same problem with DateTime, from JS I pass Javascript's Date type variable, on server I'm getting string representation, but your code in DirectMethodInvoker.GetParameterValues doesn't correctly handle this. It compares String to Nullable<DateTime> that i obviously wrong.

I think better would be to allow reflection do the job. Just handle JSON object deserialization, do not check types yourself.

elishnevsky
5 Dec 2009, 6:01 PM
It seems with latest I have problems with passing GUID strings into server-side code. Earlier with version 7 I was able to invoke controller methods that had Guid parameters - now it is broken.

What does your GUID parameter look like? What type on the server?

sergeime
5 Dec 2009, 6:27 PM
What does your GUID parameter look like? What type on the server?

On client I have simple string like "22F70AFA-D92F-418d-AED5-12AB5C067162", on server my controller method signature in like method(Guid? itemId). I'm using Nullable<> because Guid is value type and it cannot be null.

On first look I can suggest the following changes, but I believe all other attempts to use Nullable<> type found fail same way. So probably better not check types at all.


if (pType == typeof(Guid?))
{
try
{
rawValue = new Guid?(new Guid(rawValue.ToString()));
vType = typeof(Guid?);
}
catch
{
}
}

if (pType == typeof(DateTime?))
{
try
{
rawValue = new DateTime?(DateTime.Parse(rawValue.ToString()));
vType = typeof(DateTime?);
}
catch
{
}
}

if (!vType.Matches(pType))
{
throw new ArgumentException(String.Format(DirectResources.DirectMethodInvoker_WrongArgumentType, pType.FullName));
}

if (pType != typeof(Guid?) && pType != typeof(DateTime?))
{
if (pType.IsEnum && vType != typeof(string) || pType != typeof(JObject) && pType.IsComplexType() && !pType.IsEnum)
{
// for objects, arrays and enums (numeric value)
rawValue = JsonConvert.DeserializeObject(rawValue.ToString(), pType);
}
}

elishnevsky
5 Dec 2009, 7:35 PM
sergeime

Thanks for the bug report. I have updated version 0.8.2. Can you please download it again from the first post and try? Let me know if you're still having those issues. Thanks.

sergeime
6 Dec 2009, 3:24 AM
sergeime

Thanks for the bug report. I have updated version 0.8.2. Can you please download it again from the first post and try? Let me know if you're still having those issues. Thanks.

Thanks for the update, it works now like a magic :)

ddemetrius456
7 Dec 2009, 4:19 AM
Thanks for the bug report.keep up posting.thanks


________________
Advertising (http://www.webwindows.co.uk)

Bucs
8 Dec 2009, 5:21 PM
First off, thanks for your contributions to the ExtJS community. It's people like you who make ExtJS such an attractive library by helping it keep pace with the ever changing technical world around it. That being said, I myself am having a hard time keeping pace and need a little knowledge nugget in regards to ExtJS, Direct, and ASP.NET MVC. I know you're busy, so answer when you can.

I have been working with ExtJS for over a year now and love it, it's re-energized my programming efforts :) I use ExtJS obviously to generate the client side of my app, which currently uses the traditional (2.2) Ext Ajax Request framework to call into my server side to get the data it needs. My server-side is comprised of HttpHandler files that are specific to the module that is doing the request, therefore, even though I have the "normal" one page aspx application, I have many HttpHandler files (implemented as IHttpHandler ASHX files). While I don't really have a problem implementing my own "routing engine" in these ASHX files to send the client call to the correct class and method, I totally see the benefit of Direct to reduce the amount of client side code, enable the "direct" calling of server-side methods, batching of requests, etc.

However, my question at this point is why use the ASP.NET MVC design pattern as the destination point for the ExtJS Direct calls vs. using the .Net Direct Router implementation? I noticed that you were one of the initial posters in the the Direct Router forum but soon disappeared only to produce your MVC implementation soon thereafter. That makes me think you had a light bulb moment, or saw something that "routed" you this way. I also see Dave Sanders appearing in this MVC forum now who seems to be a huge contributor to the .Net Router project so that even makes me more curious as to the benefits of one approach over the other. Just to be sure, I am totally clueless right this moment on the MVC pattern so please excuse me if the answer is obvious, but I would love to know what benefits the MVC pattern provides over the initial .Net Router, if any? Is this simply two ways to skin the same cat (sorry Peta)?

I am downloading your project now and will be studying it....thanks a ton for any directional help!

elishnevsky
8 Dec 2009, 8:10 PM
Hi Bucs,

Thanks for the appreciation, it means a lot to me.

To answer your question it is important to understand, that we are not comparing two different implementations of server-side stack for Ext.Direct, but what each server-side technology has to offer and how much of that you will actually benefit. When you look at it from this perspective, the answer is obvious. To show what I mean let's see how ASP.NET Web Forms and ASP.NET MVC are different. Here we go: Compatibility of ASP.NET Web Forms and ASP.NET MVC (http://msdn.microsoft.com/en-us/library/dd381619.aspx)

As you can see, the strengths of ASP.NET Web Forms model are all about pages (i.e. Web Forms), so if you chose Ext JS for your client-side, you are not taking advantage of any of these strengths and hence pretty much defeating the whole purpose of this model.

ASP.NET MVC model, however, has strengths that you will absolutely take advantage of. Even the Views when you need to return plain HTML to show in a Ext.Panel. ASP.NET MVC offers all you will ever need for Ext JS application. And because it is built on the ASP.NET framework, it includes features such as membership, authentication, roles, and configuration. In addition to that ASP.NET has unique features such as Action Filters and Model Binders, that are also extremely useful.

To better feel the difference between the two models I suggest you to spend some time and play around with ASP.NET MVC (http://www.asp.net/mvc/). You will quickly realize that it offers the power of ASP.NET Framework without the complexity and overhead of ASP.NET Web Forms. When you write your client-side in Ext JS, it is all you need. MVC simply fits the web a lot better.

I hope I answered you question. Good luck! ;)

Bucs
9 Dec 2009, 7:47 AM
Thanks for the detailed and quick reply Eugene,

I can totally see the benefit of MVC pattern vs Web forms, without question, as the tool of choice for your server-side needs when ExtJS is on the client. What is less obvious to me though at this stage of the game, is what MVC has to offer over the .Net Router implementation, especially given the fact that you would barely even use the "V" of MVC. I mean they both seem to implement routers for RPC calls and they both generate API stubs for the client side...and since they both are implemented on top of Direct, you are on equal footing there as well.

So, I guess what you're saying is that yes, they both can get the job done, so given the two flavors, why not use the one that was born from the ASP.NET framework, which has other cool goodies that you mentioned (Action filters, Model Binders, etc). And it seems that you have done your research on the code, so as long as there is not the usual MS code bloat that has been running rampant over there for the last couple of years, I would agree with that choice.

Any more you can offer as to why use .Net MVC over the .Net Router? Or does the above pretty much cover it?

Thanks again...onward with my MVC research :)

elishnevsky
9 Dec 2009, 5:29 PM
I think what you said pretty much covers it. I see no point in creating a Web Forms app if I am not going to use any of its features. And those goodies that MVC offers are really useful.

Bucs
16 Dec 2009, 6:40 AM
Hello Eugene,

Pretty deep into my MVC review, and although an MVC will result in a bit more complexity to the overall app design, it really seems to be the way to go with where the .Net framework is headed, especially with the Entity Framework (EF) stuff. I even got a virtual machine going with MVC 2.0 and VS 2010 beta, but after working with it a little while, it's still a little buggy so backed it down to VS 2008 and MVC 1.0 for now. Was wanting to take advantage of the newer EF 4.0 changes, but as long as I implement interfaces and concrete classes, I should be able to move to that pretty easily.

I am now review your DirectController, very cool stuff. I have two quick questions:

1 - Why is there the need to manipulate the Request variable for the incoming path for the router? In other words, why the need for the following code in the Default.aspx page:



// Change the current path so that the Routing handler can correctly interpret
// the request, then restore the original path so that the OutputCache module
// can correctly process the response (if caching is enabled).

string originalPath = Request.Path;
HttpContext.Current.RewritePath(Request.ApplicationPath, false);
IHttpHandler httpHandler = new MvcHttpHandler();
httpHandler.ProcessRequest(HttpContext.Current);
HttpContext.Current.RewritePath(originalPath, false);


2 - In my ExtJS 2.2 application, I frequently had the need to returned multiple JSON data objects when dealing with forms that contained combo boxes that first needed to be populated with their potential value list, then have their value set with to the proper value from the main data object. How are you handling this in the MVC world? Or is this more of a question of using Direct batching rather than MVC? I kind of like making one call for a form and getting back all necessary sets of data to populate both the combos and the form data, so to me it's more of an MVC how-to question.

Thanks for your help!

Bucs
18 Dec 2009, 7:27 AM
Also, I am curious how you structure your MVC application project(s) if you want to separate out your business logic (service layer), models, and controllers from the the UI.

Love to hear what you are doing here...thanks!

elishnevsky
26 Dec 2009, 9:05 AM
Hi Bucs. Sorry, I couldn't reply sooner.

That piece of code in your second last post is part of MVC project template and I'm not 100% sure what it is for. ASP.NET MVC forums (http://forums.asp.net/1146.aspx) would be a better place to ask.

Regarding combo boxes there's 3 ways to deal with them:
One of them is rely on batching, as you mentioned. First you call load() method of the combo's store, and then call a method that loads the form. The two requests will be batched into one HTTP call and will be processed in the same order you called them upon return to the client.
Second option is you make one call to the server and return an object that contains the records for the combo as well as the data to load the form. Then you pass the combo records to the loadData() method of the combo box, and form data to the setValues() method of the BasicForm.
Third option is to use the override of setValue() method from this post.

elishnevsky
26 Dec 2009, 9:13 AM
We keep the controllers in the web project. All our business logic is in a separate middle-tier project in the solution. The controller actions in the web project are extremely simple, they merely call one or more middle-tier methods and return the results of those methods to the client. The model is also in a separate project.

bwaters
11 Jan 2010, 3:40 PM
I have been digging around the forums for quite a while and have not been able to find out what the basic function signatures (assuming no additional parameters) for the create, read, update and destroy methods should be.

Any assistance would be appreciated.

Thanks, Brian.

As is typical, a couple of hours (and a log of stepping through code) I was able to identify my issue. What I was experiencing was that the CRU methods could not have parameters. As it ends up, I needed to set "encode: false" for the JasonWriter object that was associated with the store. Now, for parameters, I receive the baseParams and a rows object that contain the modified rows. Currently, I am mapping this to a JObject as the only parameter to the CRU methods (this will probably change).

jason.c.cochran@gmail.com
13 Jan 2010, 2:55 AM
Bucs, what issues did you find with MVC 2? I am having some roblems as well. There appears to be something wrong with the new framework and the execution of the DirectHttpModule.

jason.c.cochran@gmail.com
14 Jan 2010, 5:28 AM
The issue is caused by MvcHandler implementing IHttpAsyncHandler now. There is a new method in the MvcHandler called ProcessRequestInit that checks to see if the request maps to a valid controller. This used to exist in ProcessRequest which is overridden in the DirectMvcHandler. This mucks things up. I have an ugly work-around in place for now. I'd love to hear if anyone has a nice fix for this.

fargs
17 Jan 2010, 9:49 AM
Hi,

I have a form that causes a server side exception. I have setup the



Ext.Direct.on('exception', function(e) {
Ext.Msg.show({
title:'Woops!',
msg: e.message,
buttons: Ext.Msg.OK,
icon: Ext.MessageBox.ERROR
});
});My form submit code is:



myform.getForm().submit({

success: function(form, action) {
store.reload();
Ext.example.msg(action.result.msg);
},
failure: actionFailedHandler,
reset: true,
waitTitle: 'Saving ...',
waitMsg:'Please wait ...'
});

Scenario:
When a server side exception occurs, I would like my Direct handler to display the message box with the exception details.

Problem:
When an exception occurs, the message box shows for a second and then disappears.

Root Cause:
The afterAction function in ext-all-debug.js is executed after the Direct exception handler. In this code, it checks the action options to see if the waitmsg has been set and hides any message box if it is. So, the message box that I set in the direct handler is being removed.



afterAction : function(action, success){
this.activeAction = null;
var o = action.options;
if(o.waitMsg){
if(this.waitMsgTarget === true){
this.el.unmask();
}else if(this.waitMsgTarget){
this.waitMsgTarget.unmask();
}else{
Ext.MessageBox.updateProgress(1);
Ext.MessageBox.hide();
}
}
if(success){
if(o.reset){
this.reset();
}
Ext.callback(o.success, o.scope, [this, action]);
this.fireEvent('actioncomplete', this, action);
}else{
Ext.callback(o.failure, o.scope, [this, action]);
this.fireEvent('actionfailed', this, action);
}
},
Solution:
OPEN FOR DISCUSSION!


Thanks and great work!

mdissel
18 Jan 2010, 2:17 AM
Is it an idea to setup a central SVN (for example on code.google.com) to host this project?

This will allow more people to help to make this a perfect asp.net mvc solution for extjs!

mdissel
18 Jan 2010, 6:55 AM
Why is it required to inherit from DirectController?

I opt for :

- using the DirectIgnore at class level to skip exporting actions from the controller. (or maybe check for the return type of the action (equal to DirectResult )


internal static bool IsDirectAction(this Type type) {
bool isDirectController = type.IsSubclassOf(typeof(DirectController));
bool ignore = (!type.IsAbstract && !type.IsSubclassOf(typeof(System.Web.Mvc.Controller))) || type.HasAttribute<DirectIgnoreAttribute>();
return (isDirectController || !ignore);
}


Changes to only return methods that return typeof(DirectResult)

internal static bool IsDirectMethod(this MethodInfo method) {
// Any controller action is a Direct method unless marked with DirectIgnoreAttribute
bool returnsActionResult = (method.ReturnType == typeof(DirectResult) || method.ReturnType.IsSubclassOf(typeof(DirectResult)));
bool ignore = method.HasAttribute<DirectIgnoreAttribute>();
return (returnsActionResult && !ignore);
}




- Implement the Direct helper function as extensions function on the System.Web.Mvc.Controller class.



Thanks
Marco

elishnevsky
18 Jan 2010, 7:08 AM
fargs
It is not related to Ext.Direct. It is the behaviour of Ext.MessageBox class and should not be discussed in this thread.

mdissel
I will try to move the source to Google Code sometimes this week. I have already created the project there, just never had time to finish it.

DirectController class does not only have helper methods. It also contain an override for ExecuteCore method, which is crucial in my implementation of Ext.Direct for MVC. It is the main reason for DirectController class to exist.

mdissel
18 Jan 2010, 7:22 AM
fargs
It also contain an override for ExecuteCore method, which is crucial in my implementation of Ext.Direct for MVC. It is the main reason for DirectController class to exist.

If you're pointing to

this.ActionInvoker = new DirectMethodInvoker();

i think this could also be configured from the DirectProvider in the ExecuteRequest (by assuming the controller is based on Controller (instead of IController).. for TDD this is not so nice, but maybe there's another way to configure a different ActionInvoker..

something like:
Controller controller = _factory.CreateController(requestContext, request.Action) as Controller;
....
controller.ActionInvoker = new DirectMethodInvoker();
(controller as IController).Execute(requestContext);

elishnevsky
18 Jan 2010, 8:05 AM
I think you are correct, thanks! I will make these changes, bump the version number and upload the new version in the next couple of days. Will also try to upload the source to Google Code.

fargs
18 Jan 2010, 1:49 PM
Hi Eugene,

The Ext.Messagebox.hide() is there to remove the progress box when the waitMsg is set on any action, so the message box is doing what I would expect.

I think the issue is that the exception is being handled and the code continues to execute the afterAction events. The failure callback in the action can be used (which executes last) but the direct exception handler has the data I want to display. The info passed to the failure callback is limited.

I have not dug into the inner workings of Direct MVC but would it be possible to have the Direct exception handler fire after all ext action events have fired?

I currently removed the waitMsg option on my action submit calls because if I use them the Direct Handler does not display the message box.

Thanks for you help.

elishnevsky
18 Jan 2010, 8:22 PM
fargs

What you are talking about is related solely to client-side part of Ext JS Framework and has absolutely nothing to do with server-side implementation of Ext.Direct. I don't have control on the server over the order in which the events are fired on the client.

elishnevsky
18 Jan 2010, 8:39 PM
Uploaded Ext.Direct.Mvc v0.8.3.

See the first post of this thread (http://www.extjs.com/forum/showthread.php?p=347906#post347906) for the download link.

Changes:
* Removed: DirectController class due to lack of necessity. Any controller is
considered a Direct controller unless marked with DirectIgnoreAttribute
which is extremely recommended.
* Changed: Helper methods that were in DirectController are now implemented as
extension methods of Controller class, so you must reference Ext.Direct.Mvc
in your controller and call the helper methods with 'this' keyword.

This means two things:

Any controller that is not intended to be used by Ext.Direct should be marked with DirectIgnore attribute. Although not required, it is highly recommended to do so, so that Ext.Direct.Mvc can completely ignore these controllers and actions they contain.
Helper methods, such as Direct() and DirectForm() must be called with this keyword - this.Direct(...); or this.DirectForm(...); - and Ext.Direct.Mvc must be referenced with using directive at the top of your controller class.

mdissel
19 Jan 2010, 2:46 AM
fargs

What you are talking about is related solely to client-side part of Ext JS Framework and has absolutely nothing to do with server-side implementation of Ext.Direct. I don't have control on the server over the order in which the events are fired on the client.

Correct. We should start a new thread discussion the clientside events in this particular situation.

mdissel
19 Jan 2010, 2:49 AM
Thanks! Quick queston. Why are you only catching the DirectException in the DirectProvider.ExecuteRequest?

} catch (DirectException exception) {

mdissel
19 Jan 2010, 5:50 AM
Thread about exception handling started at :
http://www.extjs.com/forum/showthread.php?p=428740#post428740

fargs
19 Jan 2010, 8:45 AM
Thanks mdissel! I will be continue the discussion on the new thread.

gds
19 Jan 2010, 10:08 AM
How do you set this up if the controllers are in a separate project from the view? For example my controllers are in myproject.Controllers and my views/scripts are in myproject.Web.

mdissel
19 Jan 2010, 11:29 AM
How do you set this up if the controllers are in a separate project from the view? For example my controllers are in myproject.Controllers and my views/scripts are in myproject.Web.

You can specify an assembly name in the web.config ext.direct section file..

gds
19 Jan 2010, 12:10 PM
I tried that, I'm probably missing something dumb here, do I have to do anything to my controller assembly too? In the web.config of myproject.Web I have it setup like so, referencing the controller assembly:

<ext.direct providerName="Ext.app.REMOTING_API" apiUrl="DirectApi.js" routerUrl="DirectRouter.ashx" assembly="myproject.Web.Controller" dateFormat="Iso" debug="true" />

Yet when I run it I get the same as if I referenced a nonexistent assembly. If I set the assembly to myproject.Web (which does not contain any controllers) it'll run fine until it gets to the Test.SayHello function, which is right as the myproject.Web does not contain that controller. Again, probably incredibly simple here. Thanks for your help.

elishnevsky
19 Jan 2010, 12:13 PM
In Visual Studio right-click on your project that contains the controllers and select Properties from the menu. Select Application tab. Use the value of Assembly Name field in the configuration file.

gds
19 Jan 2010, 12:36 PM
The assembly name was not the problem, the provider api was working correctly. Adding [DirectIgnore] to all but the controller I was working on solved it (as outlined by the first post in the thread). Thanks again, Ext.Direct should save me a ton of work!

elishnevsky
20 Jan 2010, 1:09 PM
Ext.Direct.Mvc is now on Google Code! Full source code is available there as well as ready packages to download and use.


Homepage:
Ext.Direct for ASP.NET MVC on Google Code (http://code.google.com/p/ext-direct-mvc/)


The latest version (and the first one on Google Code) is now 0.8.4, which is compiled with the latest Json.NET 3.5 Release 6 (included).

Please refer to the first post for more details.

mkidder
20 Jan 2010, 4:58 PM
Eugene,

I stumbled onto your project after a long hiatus from ExtJS. Absolutely wonderful work.

Do you have a timeline for MVC2 release, I saw you mention that it will be coming soon?

elishnevsky
20 Jan 2010, 6:18 PM
Eugene,

I stumbled onto your project after a long hiatus from ExtJS. Absolutely wonderful work.

Do you have a timeline for MVC2 release, I saw you mention that it will be coming soon?

Thank you! No, I don't have a specific timeline for MVC 2.0 yet. I have started looking into converting the project, but it can take some time, because I am extremely busy at work lately.

Bucs
21 Jan 2010, 4:41 AM
From what I understand, the newer features of MVC2 relate more to the View and rendering controls than anything else. So if you're using the 1 page app model and having the UI rendered from ExtJS files, then you don't really need most of that imho and MVC 1.x should be plenty. Unless of course you are using the View to generate the JS/HTML, then maybe it would be useful. Other than that, what is in the 2.0 version that you would really need? I'm curious as I haven't looked in depth at it.

Thanks...

elishnevsky
21 Jan 2010, 7:31 AM
I agree with you almost 100%. When the client-side is written entirely in Ext JS, there is nothing new and revolutionary in ASP.NET MVC 2.0, that you can benefit from. We are using MVC 1.0 at work and not planning to move to 2.0 even after it is released. However, people have a choice and should be able to use Ext.Direct with MVC 2.0 if they want to. I was working on the changes required for it last night and I am happy to say, that I am nearly done. I will let you all know, once I am finished.

elishnevsky
23 Jan 2010, 12:21 PM
Released v0.9.0 - Major update!

Latest changes:

* Changed configuration requirements. Made it much easier to configure. Setting apiUrl and routerUrl config options is no longer required and should be deleted from Web.config of your web project. The API path is now hardcoded to "/Direct/Api" and Router path is "/Direct/Router", and cannot be changed.
* Removed DirectHttpModule class, it is not needed anymore. So the related lines in Web.config file of your web project where you register this module should also be deleted.
* Removed DirectMvcRouteHandler.cs and DirectMvcHandler.cs - they are no longer needed either.
* Support for ASP.NET MVC 2.0 RC

Ext.Direct.Mvc Homepage (http://code.google.com/p/ext-direct-mvc/)

Please read the documentation (http://code.google.com/p/ext-direct-mvc/wiki/ConfiguringAndUsing) about how to configure and use Ext.Direct.Mvc.

mdissel
23 Jan 2010, 2:17 PM
Thanks for the update!
Two remarks:
- new /Direct/Api url...that's only possible if you configure asp.net to handle all requests.. why not /Direct.ashx/Api?
- debug is optional, but why not remove it completely and follow the system.web/@debug entry.

mkidder
23 Jan 2010, 2:45 PM
Eugene, WOW that was quick!! And a very nice refactoring as well.


Thanks for the update!
Two remarks:
- new /Direct/Api url...that's only possible if you configure asp.net to handle all requests.. why not /Direct.ashx/Api?
- debug is optional, but why not remove it completely and follow the system.web/@debug entry.

@mdissel - The addition of DirectController makes use of the MVC framework, negating the need for a separate HttpHandler, does it not?

elishnevsky
23 Jan 2010, 2:58 PM
Eugene, WOW that was quick!! And a very nice refactoring as well.
@mdissel - The addition of DirectController makes use of the MVC framework, negating the need for a separate HttpHandler, does it not?

That is correct.

elishnevsky
23 Jan 2010, 3:23 PM
Thanks for the update!
- debug is optional, but why not remove it completely and follow the system.web/@debug entry.

Some people have asked for ability to return full exception even in release mode.

pnrrth
15 Feb 2010, 8:48 AM
Thanks for providing a great library. It has saved me a lot of time and it works great.

I have a simple feature request: the ability to change the url for the Router. Currently it is hard-coded to generate Direct/Router. I am deploying an app in an environment that is forcing me to use Classic Mode in IIS. Because of this, I am having to append .mvc to all the controller names in order to get IIS to route these requests to ASP.Net as opposed to trying to serve up static content.

I was able to modify my main site page to include ~/Direct.mvc/Api, however subsequent calls to retrieve data still go to /Direct/Router, as opposed to /Direct.mvc/Router

I rebuilt the source code to include an additional parameter in the web.config that will allow an alternate url for the router. If you could include something like this in a future release, that would be great, then I wouldn't have to rebuild the solution each time :)

Here is a reference for getting MVC to work in Classic mode (thus requiring the .mvc extension on controllers)

http://www.asp.net/LEARN/mvc/tutorial-08-cs.aspx

elishnevsky
17 Feb 2010, 7:23 AM
pnrrth

I don't have much time to look into this. Can you please post your fix here? I'll see if I can add it to the library.
Thanks.

elishnevsky
22 Feb 2010, 8:36 AM
Ext.Direct.Mvc v0.9.1 released

Changes:

* Removed all DirectForm extension methods. The structure of return data should
always be the responsibility or choice of a developer.
* Includes binaries precompiled with ASP.NET MVC 1.0 and 2.0 RC 2.
* Bug fixes and code clean-up.

Note the first item in the change list. After a very careful consideration I have decided to permanently drop DirectForm() extension methods from the library. It will most likely require you to make changes to your code.

There were no major changes introduced in this version so you can keep using v0.9.0 if you like.

geewhizbang
25 Feb 2010, 5:03 PM
[FormHandler]
[ValidateInput(false)]
publicActionResult SavePost()
{

}
I use the form handler methods for some of my methods because they handle file uploads, and I have several different combinations of fields to pass. If you have removed this on the new version I don't quite understand why it is so bad to have FormHandler. I have three that take advantage of the FormHandler.

We are having problems only with IIS7 Server 2008 on several month old version of your router, so we tried the latest. So far we haven't gotten it to work correctly, with a debug message configuration error in your controller when we run the website.

elishnevsky
25 Feb 2010, 5:21 PM
Ext.Direct.Mvc v1.0.0 released

Changes:

* Signed the assembly with a strong name.
* Fixed: ValidateInputAttribute on a custom controller or action was not working. Request would always be validated.

I have decided to finally bump the version number to 1.0.0 because it has been pretty stable and no major changes were introduced for quite some time.

Please refer to the first post of this thread for the links.

geewhizbang: The defect with ValidateInput attribute not working was just recently found by myself. It is fixed in this version. FormHandler attribute is still there, it was never removed from the library.

geewhizbang
25 Feb 2010, 7:54 PM
Just to note that I have solved the issues converting from ~0.8 Ext.Direct.MVC to 1.0.

It was actually fairly painless. I just had to search and replace on our controller to replace "return Direct" to "return this.Direct"

The new configuration in web.config is a lot simpler.

The worst problem was actually my own brain-dead copying of the dlls into the wrong places, so the old ones were still being used.

I've been wanting to upgrade to this for some time now and the Server 2008 issue we encountered with the older version trumps my boss's paranoia about using a new version of a utility this late in the dev cycle.

We are going to really need your improved error handling mechanisms so that the debugging is easier and we have fewer mysterious failures bogging us down.

isit.gd
10 Mar 2010, 3:10 AM
i have my controllers split accross projects as it needs to be modular in design - how can i make ext.direct.mvc use these controllers?

by the looks of it GetCurrentProvider uses DirectConfig.Assembly which is a single assembly name and uses it to configure a single DirectProvider - does this mean that there is no way of splitting controller logic accross projects?

w://

Skinny79
12 Mar 2010, 5:15 PM
First of all, thanks for this great piece of work. I started using it today but i'm already very impressed!

I hope i'm not getting crazy after many hours of work today, but I have managed to get an ExtJS Grid linked to a DirectStore/Proxy and use the Ext.Direct server side implementation to expose my (test) Controller action Get and Update.

My store script looks like this :



var writer = new Ext.data.JsonWriter
({
encode: false, // Very important, defaults to true
writeAllFields: true
});

var ds = new Ext.data.DirectStore({
api: {
read: Stores.Get,
update: Stores.Update
},
paramsAsHash: false,
paramOrder: 'start|limit|sort|dir',
root: 'stores',
idProperty: 'StoreID',
totalProperty: 'total',
successProperty: 'success',
messageProperty: 'message',
sortInfo: {
field: 'Name',
direction: 'ASC'
},
fields: [
{ name: 'StoreID', type: 'int' },
{ name: 'Name', type: 'string' }
],
remoteSort: true,
writer: writer,
autoLoad: false,
autoSave: true
});

My server side Update method has the following signature :


public ActionResult Update(StoreInfo info)where StoreInfo is just a simple DTO with just two properties (StoreID, Name)

Loading the grid is no problem, editing works fine, but during the update the JSON message posted to the server looks like this :


{"action":"Stores","method":"Update","data":[{"stores":{"StoreID":321,"Name":"Winkel 23"}}],"type":"rpc","tid":3}Where "stores" is the rootProperty defined in the store.

I suspect that because the grid can send multiple updates in one request, the 'data' property contains an array. But even when I change the method parameter to StoreInfo[], all objects remain empty/null.

I traced the issue down to the call to JsonConvert.DeserializerObject in DirectMethodInvoker.cs where it seems to expect the rawValue without the (in my case) 'stores'


Can someone please give me a hit on how to handle these kind of Grid updates ?

Thanks!
Mark

bwaters
13 Mar 2010, 8:04 AM
Mark,

I too struggled with the same issues that you are facing. Below is an example of how I set up the objects and update method in C#. In the case below, there is one parameter, "extraparam", that is passed via baseParams. In this case, the root object of the store is named "rows" and matches the store field definition.



public class RecordRequest
{
public class RecordRequest_Data
{
public int id { get; set; }
public string name { get; set; }
public int type { get; set; }
}

public int extraparam { get; set; }
public RecordRequest_Data rows { get; set; }
}

public ActionResult updateRecord(RecordRequest rqst)
{
...
}
I hope that this helps.

Brian.

franklt69
17 Mar 2010, 9:16 AM
Hi, I have in the application


Ext.Direct.on('exception', function(e) {

var title = 'Direct Exception', message;

if (Ext.isDefined(e.where)) {
// Detailed error message for developer
message = String.format('<b>{0}</b><p>The exception was thrown from {1}.{2}()</p><pre>{3}</pre>', Ext.util.Format.nl2br(e.message), e.action, e.method, e.where);
var w = new Ext.Window({
title: title,
width: 600,
height: 400,
modal: true,
layout: 'fit',
border: false,
maximizable: true,
items: {
html: message,
autoScroll: true,
preventBodyReset: true,
bodyStyle: 'font-size:12px',
padding: 5
},
buttons: [{
text: 'OK',
handler: function() {
w.close();
}
}],
buttonAlign: 'center',
defaultButton: 0
}).show();
} else {
// User friendly message for end user
message = 'Error occured. Unable to process request.';
Ext.Msg.alert(title, message);
}
});




so each exception is catched in this event, but now I have a RowEditor iside the grid in bank.js file and when I do Update to BanksController.cs, method Update, if I got some exception never I get answer to the function in bold (see below), and in my case I need to cancel the edit in the row to restore the original value in the record, so how I can handle this scenario with using Ext.direct for MVC?



beforePost: function(editor, changes, r, rowIndex) {

Banks.Update(this.newRecord, r.data,
function(result, response) {
debugger //This line is never reached.
if (result.success) {

}
else
{
debugger; //This line is never reached.

}

}, this);

return true;
},


any advice please is welcome

best regards
Frank

elishnevsky
17 Mar 2010, 9:49 AM
Skinny79, it is the way DirectWriter works. There's nothing I can do to "fix" it in my library. The solution proposed by bwaters is probably what you want.

franklt69, in you case it looks like the callback function is never called. First, make sure the beforePost event actually gets fired. Second, do you have a namespace defined in the ext.direct section in your web.config file? Can you post the signature of the Update action? Also check the values of the arguments before you call the method on the client.

franklt69
17 Mar 2010, 10:23 AM
Thanks elishnevsky, yes the function beforePost: function(editor, changes, r, rowIndex) {} is actually gets fired because I can debug the Update Method in the the controller

this is the method:



[DirectHandleError]
public ActionResult Update(bool _new, DTOBankAccount aBankAccountRecord)
{
try
{
BankAccount aBankAccount = new BankAccount(aBankAccountRecord.AccountNo,
aBankAccountRecord.BankAccountID,
aBankAccountRecord.BankCode,
aBankAccountRecord.CompleteFilePath,
aBankAccountRecord.Currency,
aBankAccountRecord.DailyMappingFormat,
aBankAccountRecord.EDT_ID,
aBankAccountRecord.EDTTypeID,
aBankAccountRecord.PartialMappingFormat,
aBankAccountRecord.PendingFilePath);

if (_new)
{
var result = new
{
success = _adminService.InsertBankAccount(aBankAccount)
};
return this.Direct(result);
}
else
{
var result = new
{
success = _adminService.UpdateBankAccount(aBankAccount)
};
return this.Direct(result);
}
}
catch (Exception ex)
{
var e = new DirectException("This statement is the original exception message.");
e.Data.Add("stringInfo", "Additional string information.");
e.Data["intInfo"] = -903;
e.Data["dateTimeInfo"] = DateTime.Now;
throw e;
return this.Direct("This line is never reached.");

}

}




in the web.config I have it



<ext.direct
providerName="Ext.app.REMOTING_API"
assembly="APP.BC.Admin2" //this is the name of my assembly
dateFormat="Iso"
debug="true"
/>

best regards
Frank

daemon110282
23 Mar 2010, 5:29 AM
Hello

I am from Russia and not very good speak english. Sorry my english:)
Very good works, but i have some problems.
I am add you sample project to my project on MVC2.

In DirectProvider.cs in method ExecuteRequest in lines:


controller.ActionInvoker = new DirectMethodInvoker();
(controller as IController).Execute(requestContext);error

method not found "Void System.Web.Mvc.ControllerBase.set_ValueProvider(System.Collections.Generic.IDictionary`2<System.String,System.Web.Mvc.ValueProviderResult>)".

elishnevsky
23 Mar 2010, 6:48 AM
daemon110282,

MVC 2 Final? The current version of Ext.Direct.Mvc is compiled for MVC 2.0 RC. I will release the updated version shortly.

elishnevsky
23 Mar 2010, 10:45 AM
Ext.Direct.Mvc v2.0 Released

New in this version:


* Added support for multiple assemblies. Now you can have your Direct controllers in different assemblies, just specify the names of these assemblies in the assembly configuration option. Please keep in mind though, that a single API is generated regardless of the number of specified assemblies. So all you controllers must have unique names across all these assemblies.

* Compiled with ASP.NET MVC 2.0 Final

Please note: Ext.Direct.Mvc.dll file located directly in the Bin folder is for ASP.NET MVC v2.0. The DLL for MVC v1.0 is in the MVC 1.0 folder.

Get it here (http://code.google.com/p/ext-direct-mvc/)

geewhizbang
23 Mar 2010, 11:28 AM
Is there any way to update the current session from Ext.Direct.

Our application almost never posts back so our session is dying. I thought I had a method that worked, but it was not correct. It was keeping everyone's session alive, not just the person that had just posted back.

I am attempting update a cookie and reset the session that way, but it doesn't appear to work.



public void UpdateUserCookie(bool newCookie)
{
HttpResponse Response = HttpContext.Current.Response;
DateTime dtNow = DateTime.Now;
if (!newCookie)
{
if (_CookieExpiry.Subtract(dtNow).TotalMinutes > _Session.Timeout / 2) return;
}
string UserCookie = "kbUser";
HttpCookie cookie = new HttpCookie(UserCookie);
_CookieExpiry = dtNow.AddSeconds(_Session.Timeout * 60);
cookie.Expires = _CookieExpiry;
cookie.Values.Add("UserId", UserId.ToString());
cookie.Values.Add("Expiry", _CookieExpiry.ToUniversalTime().ToShortDateString()
+ " " + _CookieExpiry.ToUniversalTime().ToShortTimeString() + " GMT-0000");
Response.Cookies.Add(cookie);
}

elishnevsky
23 Mar 2010, 11:46 AM
There's no easy way to keep session alive. One thing you can try to do is to put a hidden iframe in your main view with a page, that reloads itself every once in a while. It must execute on the server, so make it an .aspx or .ashx handler. Something like this should do it:

<iframe src="KeepAlive.aspx" width="0" height="0" frameborder="0"></iframe>
And the page contains this:

<html><head><META HTTP-EQUIV="Refresh" CONTENT="60; URL=KeepAlive.aspx"></head><body>This is a session keep-alive page.</body></html>

elishnevsky
23 Mar 2010, 11:49 AM
Ext.Direct.Mvc v2.0 Released

New in this version:


* Added support for multiple assemblies. Now you can have your Direct controllers in different assemblies, just specify the names of these assemblies in the assembly configuration option. Please keep in mind though, that a single API is generated regardless of the number of specified assemblies. So all you controllers must have unique names across all these assemblies.

* Compiled with ASP.NET MVC 2.0 Final

Please note: From now on the Ext.Direct.Mvc.dll file located directly in the Bin folder is for MVC v2.0. The dll for MVC v1.0 is in the MVC 1.0 folder.

Please refer to the first post for download links.

prumbles
23 Mar 2010, 1:41 PM
I thought that making an AJAX call with Ext.Direct would keep the session alive. I'm using MVC and ASP.NET. Is this not true?

elishnevsky
23 Mar 2010, 3:30 PM
I thought that making an AJAX call with Ext.Direct would keep the session alive. I'm using MVC and ASP.NET. Is this not true?

Nope. Simple AJAX request doesn't keep the session alive. There's several methods to do that though, I posted one of them, which is the easiest, imho.

prumbles
23 Mar 2010, 4:15 PM
I just can't seem to figure this one out. I've tested it multiple times on my web site. I've set the session timeout to 2 minutes, and created the Session_End method in Global.asax to test when the session ends. Anytime I run an AJAX Ext.Direct method, the session ends 2 minutes later. Is it possible I have something set up differently that is causing this. Even though this IS the behavior I want, I can't expect this to be consistent if you say this should NOT be the case. What do you think is going on here?

daemon110282
23 Mar 2010, 11:05 PM
daemon110282,

MVC 2 Final? The current version of Ext.Direct.Mvc is compiled for MVC 2.0 RC. I will release the updated version shortly.

Yes, final.
Oh thanks!

geewhizbang
24 Mar 2010, 10:06 AM
I just can't seem to figure this one out. I've tested it multiple times on my web site. I've set the session timeout to 2 minutes, and created the Session_End method in Global.asax to test when the session ends. Anytime I run an AJAX Ext.Direct method, the session ends 2 minutes later. Is it possible I have something set up differently that is causing this. Even though this IS the behavior I want, I can't expect this to be consistent if you say this should NOT be the case. What do you think is going on here?

It looks like this behavior is due to the way I am caching a small object in session:



public class ContextManager
{
Dictionary <string, Context> dictContext;
Dictionary <string, string> dictQueryMap;

private ContextManager() { }

private HttpSessionStateBase _Session;
public ContextManager(HttpSessionState Session)
{
_Session = new HttpSessionStateWrapper(Session);
init();
}

public ContextManager(HttpSessionStateBase Session)
{
_Session = Session;
init();
}

private void init()
{
dictContext = new Dictionary<string, Context>();
dictQueryMap = new Dictionary<string,string>();
}

public Context Context(string Query)
{
string PortalId = null;
string ClientId = null;
Context kbContext = null;

if (dictQueryMap.ContainsKey(Query))
{
PortalId = dictQueryMap[Query];
}
else
{
string [] aQ1 =
Utility.FixNull(Utility.Extract(Query, "?", null), "").Split('&');
for (int i=0; i < aQ1.Length && PortalId == null ; i++)
{
string [] aQ2 = aQ1[i].Split('=');
if (aQ2.Length == 2)
{
switch (aQ2[0].ToLower())
{
case "cid" : case "portalid" :
PortalId = aQ2[1].Split('#')[0];
break;

case "c" : case "clientid" :
ClientId = aQ2[1].Split('#')[0];
break;
}
}
}
if (PortalId == null)
{
if (_Session["DefaultPortal"] == null)
{
kbContext = new Context(_Session);
kbContext.SetPortal(Utility.FixNullInt(ClientId, -1), -1);
if (kbContext.PortalId == -1)
{
HttpContext.Current.Response.Redirect
("/kbError.aspx?msg=1", true);
}
_Session.Add("DefaultPortal", kbContext.PortalId.ToString());
}
PortalId = Utility.FixNull(_Session["DefaultPortal"], "-1");
}
if (!dictContext.ContainsKey(PortalId))
{
if (kbContext == null) kbContext = new Context(_Session);
dictContext.Add(PortalId, kbContext);
}
}
kbContext = dictContext[PortalId];
kbContext.UpdateUserCookie();
return kbContext;
}
}
public class Context
{
private HttpSessionStateBase _Session;
private Context() { }
public DateTime LastTransactionDate;

public Context(HttpSessionStateBase Session)
{
_Session = Session;
}

// and several methods and properties here
}


This was done so that someone could be logged into more than one portal at the same time and each portal would get a separate context object, which contains the security info for our app. Some portals can be secured, others open, so we needed a way to keep them separate without having them on different URLs. The ContextManager class is used to retrieve the correct context on all three situations: MasterPage, ViewPage, and DirectRequest controller calls by parsing the URLs. The Context Manager is stored in session.

We were having problems with session going away and it mysteriously disappeared, probably about the same time I implemented this.

niklasringdahl
25 Mar 2010, 2:15 AM
Hi!

This looks really awesome! I love ExtJS and have been looking for a way to use it together with my C# skills to build a portal solution.

Is this approach good for building a web portal application? User handling, preventing DoS attacks, editorial patterns and so on?

So far, I have been looking at dropthings, a portal demo that looks good on the server side, but lacks a lot on the UI side.

Any suggestions or commens?

Thanks! (can't wait to try this!)
- Niklas

pomata
10 Apr 2010, 8:10 AM
Hi There,

Is there a reason why everything works on my machine but not on shared hosting?
I get a 404 for "Direct/Api" url.

Many thanks

Regards

oliveiraethales
23 Apr 2010, 4:52 AM
Hello!

First of all, thanks for creating this server stack for ASP.NET MVC, it's been very helpful!

I have a newbie question, but let's go. I'm simply trying to submit a Form that's inside a Window, calling a Register method o the Controller. But when I click the submit button, a JS exception is thrown, it doesn't even reach the controller. (Btw, 'get' operations works fine, like in the example project). Below is the code I'm currently using and the exception.

ExtJS Window:


Ext.namespace("MPD.UI");

CadastrarVoluntarios = Ext.extend(Ext.Window,
{
constructor: function(config)
{
config = Ext.apply({
id: 'window-cadastrarvoluntarios',
closeAction: 'hide',
collapsible: true,
closable: true,
resizable: false,
title: 'Cadastrar Voluntários',
border: false,
height: 300,
width: 500,
items: [{
xtype: 'form',
id: 'form-cadastrarvoluntarios',
labelWidth: 75,
items: [{
xtype: 'fieldset',
defaultType: 'textfield',
items: [{
fieldLabel: 'Nome',
name: 'nome',
allowBlank: false
}, {
fieldLabel: 'Endereço',
name: 'endereco',
allowBlank: false
}, {
fieldLabel: 'E-mail',
name: 'email',
vtype: 'email'
}, {
fieldLabel: 'Telefone',
name: 'telefone'
}, {
fieldLabel: 'Celular',
name: 'celular'
}]
}],
buttons:
[{
text: 'Cadastrar',
type: 'submit',
handler: function()
{
this.ownerCt.ownerCt.getForm().submit({
params: {
nome: 'nome',
endereco: 'endereco',
telefone: 'telefone',
celular: 'celular',
email: 'email'
}
});
}
}]
}],

api:
{
submit: Voluntarios.Cadastrar
},

paramOrder: ['nome','endereco', 'telefone', 'celular', 'email']
}, config);

CadastrarVoluntarios.superclass.constructor.call(this, config);
},

parent: null,

init: function(parent)
{
this.parent = parent;
parent.cadastrarVoluntarios = this;
}
});


Controller:


namespace MaisPertoDeDeus.Controllers
{
public class VoluntariosController : Controller
{
[FormHandler]
public ActionResult Cadastrar(string nome, string endereco, int telefone, int celular, string email)
{
return this.Direct(null);
}
}
}


Any help is appreciated. Thanks in advance!

steffen.rahn
27 Apr 2010, 10:30 PM
I've got the following Problem while using linq with stored procedures:

I convert the ISingelResult with AsQueryable() to IQueriable but I alsways get a
The query results cannot be enumerated more than onceException.

When I got it right, I have to create a ISingeResult wrapper class? Is that the right way or is there a better way?

@oliveiraethales:
Maybe I am blind, but I dont see the exception text...

@pomata:
Is there the correct path in your view? Try Url.Content("~/Direct/Api")
Othwise check if there are no restrictions that prevent the provider registration

steffen.rahn
28 Apr 2010, 12:29 AM
Who ever get's the same Problem; ToList() works quite fine. I only tried it twice (I forgot the second statement in the other class), what cause the whole thing to explode.

franklt69
14 May 2010, 12:43 PM
Using Ext.Direct.Mvc.dll 2.0.0.0 locally all work ok when I upload the application to the server I get this error":


provider is undefined
if(!provider.events){

the error happen here

Ext.Direct.addProvider(Ext.app.REMOTING_API);
with firebug I can see Ext.app.REMOTING_API = null

in the web config I have:



?xml version="1.0"?>
<configuration>
<configSections>
<section name="ext.direct" type="Ext.Direct.Mvc.Configuration.DirectSection, Ext.Direct.Mvc" />
</configSections>
[B] <ext.direct
providerName="Ext.app.REMOTING_API"
assembly="ET.BS.Admin"
dateFormat="Iso"
debug="true"
/>
<connectionStrings>
<!-- <add name="SampleConnectionString" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Sample.mdf;Integrated Security=True;User Instance=True" providerName="System.Data.SqlClient" /> -->
<!--<add name="SampleConnectionString" connectionString="Data Source=SAFETYPAY-DEV1;Initial Catalog=SAMPLE.MDF;Integrated Security=True" /> -->
<add name="mySQLConnectionString" connectionString="server=localhost;user id=root; password=; database=etdb"/>
</connectionStrings>
<system.web>
<compilation debug="true">
<assemblies>
<add assembly="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
</assemblies>
</compilation>
<authentication mode="None" />
<pages>
<namespaces>
<add namespace="System.Web.Mvc"/>
<add namespace="System.Web.Mvc.Html"/>
<add namespace="System.Web.Routing"/>
</namespaces>
</pages>
<httpModules>
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</httpModules>
</system.web>
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<providerOption name="CompilerVersion" value="v3.5"/>
<providerOption name="WarnAsError" value="false"/>
</compiler>
</compilers>
</system.codedom>
<!--
The system.webServer section is required for running ASP.NET AJAX under Internet
Information Services 7.0. It is not necessary for previous version of IIS.
-->
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true">
<remove name="UrlRoutingModule" />
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</modules>
<handlers>
<remove name="MvcHttpHandler" />
<remove name="UrlRoutingHandler" />
<add name="MvcHttpHandler" preCondition="integratedMode" verb="*" path="*.mvc" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd" type="System.Web.HttpForbiddenHandler, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</handlers>
</system.webServer>
</configuration>



I ma missing somethig?

a little help is welcome

Regards
Frank

franklt69
14 May 2010, 2:15 PM
where I found information about to use the latest version of Ext.Direct.Mvc and MVC1 because I think the server where I am deploying don't support mvc2, but I need the setting in the web.config too because I am confused

regards
Frank

franklt69
17 May 2010, 11:51 AM
I need some help, how I can detect where is the error:
provider is undefined
[Break on this error] if(!provider.events){


IN Firebug I saw http://lxxxx/Admin1/Direct/Api 500 Internal Server Error
I was testing in rackspace hosting, an app using ext.direct.mvc 0.6.2 and it worked ok, now I deployed the demo application (Ext.Direct.Mvc.Demo) using version 2 but MVC1 and I get in the cloud this error:



<b> Description: </b>The application attempted to perform an operation not allowed by the security policy. &nbsp;To grant this application the required permission please contact your system administrator or change the application's trust level in the configuration file.
<br><br>

<b> Exception Details: </b>System.Security.SecurityException: That assembly does not allow partially trusted callers.<br><br>


so someone had has this error?

regards
Frank

aritchie
17 May 2010, 12:58 PM
The assembly needs the following attribute (usually in AssemblyInfo.cs)

[assembly: AllowPartiallyTrustedCallers]

sspark
17 May 2010, 4:44 PM
How about same name of Contrller in Different Area ?

I tried to access http://<host>/Direct/Api, then I got error which is "Action Options has already been configured".
Because, I have same name of Controllers in different Areas.

franklt69
18 May 2010, 6:48 AM
Ok Thanks so much aritchie the solutions was add in Ext.Direct.Mvc\Properties\AssembyInfo.cs

[assembly: AllowPartiallyTrustedCallers]

regards
Frank

franklt69
18 May 2010, 8:34 AM
Other issue deploying an app

I have the application running ok locally then I upload the app to a new server with IIS6 and I getting this error


in Js:
provider is undefined

// if provider has not already been instantiated
37534 if(!provider.events){
37535 provider = new Ext.Direct.PROVIDERS[provider.type](provider);
37536 }


Get http://app.demo.com/Direct/Api 404 Not Found with firebug



<h1>The page cannot be found</h1>
The page you are looking for might have been removed, had its name changed, or is temporarily unavailable.
<hr>
<p>Please try the following:</p>
<ul>
<li>Make sure that the Web site address displayed in the address bar of your browser is spelled and formatted correctly.</li>
<li>If you reached this page by clicking a link, contact
the Web site administrator to alert them that the link is incorrectly formatted.
</li>
<li>Click the <a href="javascript:history.back(1)">Back</a> button to try another link.</li>
</ul>
<h2>HTTP Error 404 - File or directory not found.<br>Internet Information Services (IIS)</h2>



so any Idea if I have to setup something in the IIS?

regards
Frank

franklt69
18 May 2010, 11:57 AM
I am researching about this error
Get http://app.demo.com/Direct/Api 404 Not Found with firebug because
it is weird, demo work ok using local server http://localhost:53794/Default.aspx in the same computer I change the application to run on IIS and I get http://app.demo.com/Direct/Api 404 Not Found, someone is testing the version 2.0 with IIS6 ? I was testing old version Ext.Direct.Mvc-0.6.2 and work ok with IIS6

regards
Frank

franklt69
19 May 2010, 6:49 AM
I found a solution in this article for IIS6 http://professionalaspnet.com/archive/2007/07/27/Configure-IIS-for-Wildcard-Extensions-in-ASP.NET.aspx

regards
Frank

franklt69
19 May 2010, 2:03 PM
some have idea about this issue using the demo application version 2.0 in rackspace cloud I get this error when I call any method in the server:



<b> Exception Details: </b>System.Security.VerificationException: Operation could destabilize the runtime.<br><br>

<b>Source Error:</b> <br><br>

<table width=100% bgcolor="#ffffcc">
<tr>
<td>
<code>

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.</code>

</td>
</tr>
</table>

<br>

<b>Stack Trace:</b> <br><br>

<table width=100% bgcolor="#ffffcc">
<tr>
<td>
<code><pre>

[VerificationException: Operation could destabilize the runtime.]
SetAction(Object , Object ) +32
Newtonsoft.Json.Serialization.DynamicValueProvider.SetValue(Object target, Object value) +81

[JsonSerializationException: Error setting value to 'Action' on 'Ext.Direct.Mvc.DirectRequest'.]
Newtonsoft.Json.Serialization.DynamicValueProvider.SetValue(Object target, Object value) +220
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonReader reader, Object target) +330
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, String id) +657
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateAndPopulateObject(JsonReader reader, JsonObjectContract contract, String id) +110
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, Object existingValue) +837
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValue(JsonReader reader, Type objectType, JsonContract contract, Object existingValue, JsonConverter memberConverter) +234
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType) +71
Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) +48
Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) +105
Newtonsoft.Json.JsonConvert.DeserializeObject(String value, JsonSerializerSettings settings) +66

Newtonsoft.Json.JsonConvert.DeserializeObject(String value) +42
Ext.Direct.Mvc.DirectProvider.Execute(RequestContext requestContext) in DirectProvider.cs:169
Ext.Direct.Mvc.DirectController.Router() in DirectController.cs:45
lambda_method(ExecutionScope , ControllerBase , Object[] ) +39
System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters) +17
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +178
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +24
System.Web.Mvc.&lt;&gt;c__DisplayClassa.&lt;InvokeActionMethodWithFilters&gt;b__7() +53
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation) +258
System.Web.Mvc.&lt;&gt;c__DisplayClassc.&lt;InvokeActionMethodWithFilters&gt;b__9() +20
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +193
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +382
System.Web.Mvc.Controller.ExecuteCore() +123
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +23
System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +7
System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext) +144
System.Web.Mvc.MvcHandler.ProcessRequest(HttpContext httpContext) +54
System.Web.Mvc.MvcHandler.System.Web.IHttpHandler.ProcessRequest(HttpContext httpContext) +7
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +181
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean&amp; completedSynchronously) +75




regards
Frank

Tarabass
7 Jun 2010, 10:57 AM
Great job! Many thanks for that. Just the push in the back I needed, since i'm new to mvc .net and extjs. Will study on it! :D

halcwb
19 Jun 2010, 1:56 AM
I keep running in a System.NullReferenceException: DirectRequest is null exception. I post a form to the following controller:


[FormHandler]
[ValidateInput(false)]
public ActionResult GenFormLogin(string user, string password)
{
bool login = (Informedica.GenForm.Library.Security.
GenFormPrincipal.Login(user, password));

//return this.Direct(new LoginResponse(login, "failure"));
return this.Direct(RoleNameList.GetNameValueList());
}

[Serializable]
private class LoginResponse
{
private bool _Success;
private string _Title;

public LoginResponse(bool success, string title)
{
_Success = success;
_Title = title;
}

public bool Success
{
get { return _Success; }
set { ;}
}

public string Title
{
get { return _Title; }
set { ;}
}
}
When I debug my code, the program passes the controller code without problems. But in my webbrowser I get the null reference exception. The javascript code I use to submit the form is:


handler : function() {
loginForm.getForm().submit({
success : function(f, a) {
debugger;
Ext.Msg.alert('Success', 'It worked');
},
failure : function(f, a) {
debugger;
Ext.Msg.alert('Warning', a.failureType);
}
});
}
But I do not think the problem is not on the client side but in my this.Direct return object. I also tried passing a null, boolean, string, anonymous class like : new { succes = true, title: "failure} etc...

Any help will be greatly appreciated.

geewhizbang
19 Jun 2010, 12:58 PM
In the project I just completed, we dynamically load views on each tab so that all of the code doesn't have to be loaded at once. It also allows you to dynamically populate the code with some data, which can help maintain security.



//in the code that initializes ExtJS you set:
Ext.UpdateManager.defaults.loadScripts = true;

//item that auto executes a view (the only property that is required is the autoLoad,
//but I show some other properties to give some context.

var Items =
[
{
region: 'center',
layout: 'anchor',
id: 'YourId',
autoLoad: 'yourViewFolder/yourView'
}
];


We could also use a function to load a view script (or external js file on the fly)


YourApp.RunScript = function(url, fn)
{
if (Ext.isDefined(fn))
{
fn();
}
else
{
if (! Ext.isDefined(YourApp.ScriptContainer))
{
YourApp.ScriptContainer = new Ext.Window
({ x:-100, y: -100, hidden: true, autoDestroy: false, hideMode: 'offsets' });
}
YourApp.ScriptContainer.add(new Ext.Panel({ autoLoad: url, hidden:true } ));
YourApp.ScriptContainer.doLayout();
}
};
YourApp.RunScript('/yourFolder/yourView', yourFunctionInFile)


With this arrangement we had only one view page running at the time, but it could load child views of code in new tabs. This way we didn't have to load all of the code at once, but we could dynamically load new code any time we wanted to. The loaded code could use any common objects we wanted. The other nice thing about this code is that it could be called more than once. If the code was already loaded, it runs fn(), but if not it autoloads the code and runs the code.

geewhizbang
19 Jun 2010, 1:09 PM
I'm building an app that doesn't need much in the way of controls, but the directRequest handlers and data stores would be nice.

What is the minimum Javascript code that needs to be included to handle DirectRequests and have data store objects. Or is this too complicated to even be considered as an option?

Update: So far, trying to load the least amount of code hasn't worked. Going thru the API help documents, I've loaded about a dozen js files and I still have issues. This is approaching perhaps one third of the entire ext-all, so perhaps this isn't worth doing.



pkgs/ext-foundation.js
pkgs/Ext.js
pkgs/data-foundation.js
pkgs/data-grouping.js
pkgs/data-json.js
pkgs/data-list-views.js
pkgs/data-xml.js
pkgs/jsonProvider.js
pkgs/remotingProvider.js
pkgs/pollingProvider.js
ext/pkgs/direct.js
ext/pkgs/Component.js
ext/pkgs/container.js
ext/pkgs/boxComponent.js
ext/pkgs/viewport.js
ext/pkgs/pkg-buttons.js

mdissel
24 Jun 2010, 12:38 AM
I want to discuss a change in detecting "IsDirectMethod":
- remove the assembly configuration and just scan every assembly (skipping 'known assemblies like system.*')
- optionally add a skipAssembly configuration to configure assemblies that can be skipped
- change the IsDirectMethod to:


internal static bool IsDirectMethod(this MethodInfo method) {
if (method.ReturnType == typeof(DirectResult) || method.ReturnType.IsSubclassOf(typeof(DirectResult)))
return true;
if (method.ReturnType == typeof(ActionResult) || method.ReturnType.IsSubclassOf(typeof(ActionResult)))
return method.HasAttribute<DirectIncludeAttribute>();
return false;
}


Thanks

elishnevsky
24 Jun 2010, 8:11 AM
Why would you want to scan all assemblies? I think most of the time in an average project there will be one assembly containing Direct controllers. Also in our project, for example, we are using quite a few third-party assemblies and it is much easier to specify which assemblies to scan (in our case it's only one) as opposed to which to skip.

mdissel
24 Jun 2010, 9:37 AM
In our situation we are working with "plugin" controllers... Every customer can have more or less controllers, changing config files is something we want to avoid. (convention over configuration)

elishnevsky
24 Jun 2010, 11:13 AM
Interesting. I need to have a think on this one :) How can I see your code that scans all assemblies except system.*?

geewhizbang
29 Jul 2010, 12:38 PM
I am beginning a new project that has a WCF Service handling all of the backend requests.

I liked the code we ended up on my last job with the Ext.Direct handler, so my question for this WCF architecture, is using your Ext.Direct handler a good way to go?

Or would this be an unnecessary abstraction for this project?

I'm thinking that it would be fairly easy to write a filter that writes out direct request functions for all of the functions exposed by the WCF object.

elishnevsky
29 Jul 2010, 12:47 PM
Can't say, I am not familiar with WCF at all.

zam6ak
25 Aug 2010, 8:26 AM
Wiki page says that .NET 3.5 is requird...
http://code.google.com/p/ext-direct-mvc/wiki/ConfiguringAndUsing

Will this work for .NET v4 ?
Will it work with latest JSON.NET releases? (Release 8)

nightwatch
25 Aug 2010, 10:09 AM
I don't remember if I ever posted it here, but some time ago I have implemented my own version of Ext Direct stack as a part of 'boson-mvc' project. It's an open source library so you can use it freely. My implementation is based on Castle Windsor container. The source code can be compiled under vs 2010 and I don't provide a binary version as for now. The project contains also the 'boson' view engine for generating dynamic json or xml from asp.net mvc views.
Boson mvc is used in production software so it's been tested and is mature somehow. Unfortunately the documentation is non existent so you'll have to figure out everything yourself.Anyway I hope someone will find it useful.
Address: http://code.google.com/p/boson-mvc/

elishnevsky
25 Aug 2010, 11:22 AM
zam6ak, I've just converted the project to VS 2010 and compiled with .NET 4.0. Also updated Json.NET dll to the latest. Please download it from the project homepage on Google Code: http://code.google.com/p/ext-direct-mvc/

nightwatch, this topic is only for discussing my Ext.Direct .NET library for ASP.NET MVC. If you want to promote and discuss your implementation, please start a new topic. Thanks.

nightwatch
25 Aug 2010, 1:12 PM
sorry, I thought it's about all asp.net mvc implementations.

zam6ak
26 Aug 2010, 10:08 AM
@elishnvsky - Very nice, thank you!

bt_bruno
14 Sep 2010, 11:42 AM
I keep running in a System.NullReferenceException: DirectRequest is null exception. I post a form to the following controller:


[FormHandler]
[ValidateInput(false)]
public ActionResult GenFormLogin(string user, string password)
{
bool login = (Informedica.GenForm.Library.Security.
GenFormPrincipal.Login(user, password));

//return this.Direct(new LoginResponse(login, "failure"));
return this.Direct(RoleNameList.GetNameValueList());
}

[Serializable]
private class LoginResponse
{
private bool _Success;
private string _Title;

public LoginResponse(bool success, string title)
{
_Success = success;
_Title = title;
}

public bool Success
{
get { return _Success; }
set { ;}
}

public string Title
{
get { return _Title; }
set { ;}
}
}
When I debug my code, the program passes the controller code without problems. But in my webbrowser I get the null reference exception. The javascript code I use to submit the form is:


handler : function() {
loginForm.getForm().submit({
success : function(f, a) {
debugger;
Ext.Msg.alert('Success', 'It worked');
},
failure : function(f, a) {
debugger;
Ext.Msg.alert('Warning', a.failureType);
}
});
}
But I do not think the problem is not on the client side but in my this.Direct return object. I also tried passing a null, boolean, string, anonymous class like : new { succes = true, title: "failure} etc...

Any help will be greatly appreciated.


I got this error too :(


public ActionResult Index()
{
var response = new
{
totalCount = 20,
root = new object[]{
new { Name = "Client 1" },
new { Name = "Client 2" },
new { Name = "Client 3" },
}
};

return this.Direct(response);
}


P.S.: this asp.net mvc ext direct implementation is awesome!

dan_b
21 Sep 2010, 3:48 AM
I got this error too :(


The clue is in the error "DirectRequest is null". Are you going via the Ext Direct API or straight to the controller action?

cracknix
22 Sep 2010, 3:53 AM
hi,

how to register my controller to the api....

i did everything same like on the MVC Solution, but on the Demo i get

<script type="text/javascript" src="<% = Url.Content("~/Direct/Api") %>"></script>
Ext.app.REMOTING_API={ "url": "/Direct/Router", "type": "remoting", "actions": { "Test": [ { "name": "SayHello", "len": 0 }, { "name": "EchoDate", "len": 1 }, { "name": "AddNumbers",

on my own project for the same come


<script type="text/javascript" src="<% = Url.Content("~/Direct/Api") %>"></script>

Ext.app.REMOTING_API={ "url": "/Direct/Router", "type": "remoting", "actions": { "Direct": [ { "name": "Api", "len": 0 }, { "name": "Router", "len": 0 } ] } };

Error: Test is not defined



How to register TestController to the API?

Webconfig:

<configSections>
<section name="ext.direct" type="Ext.Direct.Mvc.Configuration.DirectSection, Ext.Direct.Mvc"/>
</configSections>
<ext.direct providerName="Ext.app.REMOTING_API" assembly="Ext.Direct.Mvc" dateFormat="Iso" debug="true"/>

dan_b
23 Sep 2010, 12:38 AM
<configSections>
<section name="ext.direct" type="Ext.Direct.Mvc.Configuration.DirectSection, Ext.Direct.Mvc"/>
</configSections>
<ext.direct providerName="Ext.app.REMOTING_API" assembly="Ext.Direct.Mvc" dateFormat="Iso" debug="true"/>[/QUOTE]

assembly="Ext.Direct.Mvc" should be assembly="Your.Controllers.Assembly"

Zarathustra
23 Oct 2010, 12:08 PM
Hi all,

I've some problems to make the configuration works. I have a web project and another controller project in my solution. I read the tutorial and configure my web.config as it should be. My problem is when I try to add the provider under Ext.onReady function, I get an error like :

'events' is Null or not an objet
This is coming from the addProvider method of the ext-all file. I think ext is not encountering the assembly of my controller project (I checked all the names dozen of times) cause the provider parameter of the addProvider method is received undefined...

I have downloaded the test project available with Ext.Direct.Mvc and it runs well. Actually, I'm sure the problem is the assembly because putting a wrong name in the web.config of the demo solution cause the same issue. But I'm sure I have my assembly name correct.... :(

Any suggestion would be appreciated :)

Bucs
27 Oct 2010, 10:43 AM
Getting ready to jump into MVC and Direct for the first time as I think the pattern is pretty cool and here to stay, especially since ExtJS (err Sencha) apps don't really use ASP.net controls or the Server Page Event model. Will this implementation of Ext.Direct for ASP.NET MVC work fine with the new ASP.NET MVC 3, or are they any breaking changes or gotchas? From my understanding, most of the new stuff is related to Views which I wouldn't use anyway, but always nice to start with the latest. The JSON binding improvements seem nice though.

Suggestions, comments appreciated!

Thanks...

dan_b
28 Oct 2010, 5:30 AM
No problems using this with MVC 2 and 3.

I only have one view in my projects, Home/Index which pulls in all the js files. Extjs is essentially the V in my MVC, with my controllers only returning snippets of JSON. I really really like the way this separates the UI from business logic and data access in the controllers - I could, say, swap out my backend for a PHP one and as long as it returned the same data the front end would be blissfully unaware.

And yes, most of the new stuff in MVC 3 I don't use either.

Bucs
29 Oct 2010, 6:53 AM
After a pretty decent review of MVC, I love the pattern, looks very powerful and flexible. The one issue that I cannot really find a whole lot of info on, especially in regards to the Ext.Direct ASP.NET MVC router calls, is security. I've read the few articles on the MVC site, but they are pretty basic and gloss over a lot of the details by just telling you to use the Membership provider. I am not a big fan of that provider number one, and number two I am bolting on a new external web application to pull data from an internal web applicaiton (thru firewall) and will have to authenticate against the internal app's business security layer, passing in username/password.

My question really has sseveral parts:
1) How do you protect an entire MVC project's controller actions via Forms authentication, i.e. require that the user is authenticated before allowing use?
2) What is best way to do forms authentication for an MVC app, include a webform in the MVC project?
3) Is your only choice to implement the standard or a custom Membership Provider?
3) If I performed my own authentication methodology and created my own form auth ticket and then added this ticket t the context via context.Response.Cookies.Add(authCookie), does this get passed back and forth with the Direct calls or can I do something to make this happen?

Sorry for the lame questions on this...kinda clueless on how to get security working in this environment after coming form the ASP.Net world.

Thanks for any direction!

dan_b
29 Oct 2010, 11:50 AM
In MVC security is pretty much left up to you to handle.

1) FormsAuthentication.SetAuthCookie(username, false); then slap an
[Authorize] attribute on your controller or action.

2) See above.

3) Not at all

4) Absolutely, see (1). It's as simple as that.

You probably want to read this (http://blog.nvise.com/?p=26) and this (http://stackoverflow.com/questions/1472610/how-do-you-deal-with-authorisation-on-actions-that-return-results-other-than-view) regarding unauthorized requests.

Bucs
29 Oct 2010, 1:46 PM
Thanks Dan for the reply. Without taking up too much of your time, could you explain the organization of your projects, what type of projects they are (Web, MVC, etc), where and how exactly you are capturing the login info, and how are you passing those credentials around the various projects, to ensure all controller actions are not exposed to public use? I undertand the attributes you're using for ensureing authentication prior to use, but more interested how this all works when split out across all the projects that I see people are doing.

Thanks so much!!!

dan_b
1 Nov 2010, 3:41 AM
Hi mate,

My solution is a typical n-tier business app built on Extjs, Asp.net MVC, NHibernate/RhinoCommons/Castle Windsor stack.

I've got a Commons project with bits and bobs I use across all my projects, Core with my domain entities and business logic, Data.Nhibernate contains some Repository<T> extensions and things event listeners for Auditing and Soft-Deletes, Unit Tests, then the web bit... I have split my controllers out into a separate class library, so my Web project contains nothing but HTML, CSS, JS and images. I use the WindsorControllerFactory from MVCContrib for this, I really recommend doing it as it can be a pain in the arse scrolling up and down all the time looking for your controllers.

My Authentication controller looks like this:



/// <summary>
/// Controller for managing logging on and off
/// </summary>
[DirectHandleError]
public class AuthenticationController : BaseController
{
private const int PASSWORD_ATTEMPT_WINDOW = 5;
private const int PASSWORD_MAX_INVALID_ATTEMPTS = 5; // 5 invalid passwords in 5 mins locks the account

[FormHandler]
public ActionResult Login(string userName, string password)
{
string message = "No user found with that username";
bool success = false;
bool mustChangePassword = false;

if (userName.IsNullOrEmpty())
{
message = "No username supplied";
return this.Direct(new {success, message, mustChangePassword});
}

if (password.IsNullOrEmpty())
{
message = "No password supplied.";
return this.Direct(new {success, message, mustChangePassword});
}

User user = NamedRepository<User>.GetByName(userName);

if (user != null)
{
if (user.IsLockedOut)
message =
"Your account has been locked. Please contact system administrator.";
else if (!user.IsEnabled)
message = "Your account is disabled. Please contact system administrator.";
else
{
success = user.Login(password, PASSWORD_ATTEMPT_WINDOW, PASSWORD_MAX_INVALID_ATTEMPTS);
if (success)
{
message = "Successfully logged on";
/* Store the User by the Primary Key
* this enables us to make use of 2nd Level Cache and avoid hitting the DB on each request*/
FormsAuthentication.SetAuthCookie(user.Id.ToString(), false);
mustChangePassword = user.MustChangePassword;

//have decided to disable success audit as it fills up the logs
//with junk
//user.AddAuditEvent(new AuditEvent(user, "Successful login."));
}
else
{
message = string.Format("Incorrect password. You have {0} attempts remaining.",
PASSWORD_MAX_INVALID_ATTEMPTS - user.FailedPwdAttemptCount);

var ip = HttpContext.Request.UserHostAddress;

user.AddAuditEvent(user.IsLockedOut
? new AuditEvent(user,
string.Format(
"Failed login from {0} - Account is locked out.", ip))
: new AuditEvent(user,
string.Format(
"Failed login from {0}", ip)));
}
}

//Commit changes to the user to the database
//eg. last login/failed login etc
Repository<User>.Save(user);
UnitOfWork.Current.TransactionalFlush();
}

return this.Direct(new {success, message, mustChangePassword});
}

public ActionResult LogOut()
{
if (CurrentUser != null)
{
CurrentUser.AddAuditEvent(new AuditEvent(CurrentUser, "Logged out."));
Repository<User>.Save(CurrentUser);
UnitOfWork.Current.TransactionalFlush();
}
FormsAuthentication.SignOut();
var returnObject = new {success = true, message = "Successfully logged out"};

return this.Direct(returnObject);
}

[Authorize]
public ActionResult ChangePassword(string newPassword)
{
if (CurrentUser != null)
{
CurrentUser.ChangePassword(newPassword);
CurrentUser.AddAuditEvent(new AuditEvent(CurrentUser, "Changed Password"));
Repository<User>.Save(CurrentUser);
UnitOfWork.Current.TransactionalFlush();

return this.Direct(new {success = true, message = "Changed Password"});
}

return this.Direct(new {success = false, message = "No currently logged in user"});
}
}


on the client it's simply:


{
xtype: 'form',
defaultType: 'textfield',
labelWidth: 70,
frame: true,
api: {
submit: Authentication.Login
},
labelAlign: 'right',
defaults: formItemDefaults,
items: [
{
fieldLabel: 'User Name',
name: 'userName'
},
{
inputType: 'password',
fieldLabel: 'Password',
name: 'password'
}
]
}

and a form.submit(); does the magic.

So in my case a User is an Entity defined in the Core/Domain project containing the logic for validating passwords, etc. In your case it could be something retrieved from a 3rd party app across a firewall or whatever. It really is up to you how you want to do it.. in my case i store the users PK as the forms auth identity.
As you can see there's an [Authorize] on the ChangePassword action, if you tried to hit that without having logged in Asp.net kicks back with a "302 Found" and redirects to the Forms Auth login screen. You could override this to provide a {success = false, message = "You're not allowed to do that!"} JSON object as per links provided in previous post. This is how i handle authenticated but unauthorized requests, I use RhinoSecurity for that.

It really is that simple, the great thing about mvc is that you're not tied into using things like the crappy Membership Provider API, Login Controls etc etc and you can even do it without a single .aspx page if you wanted to.

One of the things I like about ext direct is that if it can serialize and deserialize dtos from C# to JS quite happily, I can't remember the last time I had to parse e out of a FormCollection.

Hope this helps?

PS: I highly recommend getting you hands on ExtJSInAction, chapters 16 and 17 deal with how to build and organise a "big application" and I found them indispensable.

Bucs
3 Nov 2010, 1:37 PM
Wow Dan, thanks for you time on that...seriously. That all makes perfect sense, although I am not familiar with NHibernate, RhinoSecurity, OR Castle Windsor stack :) I usually use the "hand roll everything from scratch" approach, but might be time for a change. I think I really need to just get an ASP.NET MVC app with Ext.Direct and authentication up and running first, then decide how to incorporate all these new gadgets.

Also, are you doing anything with Roles at all? I would like to be able to use roles in the Authorize attribute so wondering where that is best to do. In ASP.Net, I did this in the Application_AuthenticateRequest where I would check if authenticated and if so, then pull out the encrypted roles from the cookie and rehydrate a custom security principle and attach that to user's context. Where/how should this be done in ASP.NET MVC?


Thanks again for all your time and info!
Randy

dan_b
4 Nov 2010, 2:54 AM
Sending you a PM as this is going out of scope of Ext.Direct discussion. :)

ovidiu
5 Nov 2010, 7:39 AM
Hi,
I'm new to Ext.Direct and I'm trying to migrate my views from an MVC project to extjs.
Question is: why I can't have 2 methods in same controller with different HttpVerb
For example if I have:
public virtual ActionResult MyResource()
{
var modelVM = ServiceFactory.New<MyModel>();
/..
return View(modelVM);
}

[HttpPost]
public virtual ActionResult MyResource(MyModel modelVM)
{
/..
return View(model);
}
I get an error:"Method MyResourcehas already been configured for action Home" when requesting: http://localhost:32529/Direct/Api

elishnevsky
5 Nov 2010, 8:33 AM
Because Ext.Direct.Mvc generates proxy methods in JavaScript for all your controller actions. And if you have multiple methods with the same name, Ext.Direct wouldn't know which one to call. On the client method names must be unique. If you absolutely have to have actions with the same name on the server, then give them different aliases by marking them with ActionName attribute. Ext.Direct.Mvc will use them instead of the actual method names when it generates client-side proxy methods.

Bucs
5 Nov 2010, 8:43 AM
I am playing around with setting up an MVC project with Ext.Direct.Mvc. I have split my projects into Controller, Model, and Web projects. I have added the ext.direct section to the Web.config of the Controller project and added the script tag to the header section of the Default.aspx in the Web project. But where does the call "Ext.Direct.addProvider(Ext.app.REMOTING_API);" supposed to go? I tried to put it in the Application_Start of the Global.asax of the Controller project but there is no addProvider method in the Ext.Direct namespace? What am I doing wrong here, am I using the wrong version of the Ext.Direct.Mvc (downloaded from 1st page "latest") for .Net 4.0?

Thanks for your help and this MVC direct stack!

UPDATE: Ooops, ok...in the OnReady of the JS files to access the API...duh. :)

elishnevsky
5 Nov 2010, 9:26 AM
Thanks for your help and this MVC direct stack!

UPDATE: Ooops, ok...in the OnReady of the JS files to access the API...duh. :)

:)

You are welcome.

Bucs
5 Nov 2010, 11:36 AM
Well, I'm trying to work my way through this without bothering you guys by looking at the demo, but still having some issues.

Not really understanding the "<script type="text/javascript" src="/Direct/Api"></script>" code. I have put that ref in my main aspx file (head section) in my UI Web project, knowing that it is supposed to generate the client side proxy. But do I have to manually create this directory structure in the web project first, so the code can generate and store the proxy there, or is that done on the fly?

Also, how do I know if there is a problem generating the proxy? Right now I am getting an error on the addProvider method of ext-all.js, leading me to believe that the proxy generation is blowing up or something. Looks like the provider param is null when passes into the addProvider method. Kinda stuck here in trying to figure out what the problem is with generating the proxy.

Also, is the latest Ext.Direct router compatible with ExtJS ver 3.3? That is what I am using.

Any help greatly appreciated! Thx....

Bucs
5 Nov 2010, 1:19 PM
Ok, guess the best way to learn is first completely confuse the cr#p out of yourself, then slowly work back towards the light. I was getting so concerned with separation of responsibilities that I had my controllers in one MVC project and the web UI in another ASP.NET project thinking that I need to separate my controllers from the UI. However, this essentially creates two webs which is not smart as this was confusing the script ref to the API as it was trying to ref the API which was essentially being served by a separate web. If you must separate your controllers out, do it the smart way (as suggested by dan_b) which is to make them class libraries.

I love publishing my idiocracy...but who knows, it might helps others in the same boat :)