There are some specifics for calling WebMethods from ExtJS.
By default, ExtJS is passing a call to Ajax WebService as GET, with one default parameter "_dc" of the Get request and request looks like this:
http://localhost:60972/WebService1.asmx/GetJamesBondActors?_dc=1312120714323&myTest=a&bar=foo&page=1&start=0&limit=25
Also, any extraParams, or your operation parameters goes inside Request url.
You can notice that there are some extra parameters that ExtJS is passing in based on what component you are using (page, start, limit)
Don't worry about the _dc parameter, this one is added there automatically unless you disable caching and should be there for better handling of caching of each request.
How to read you ExtJS parameters a simple way ?
Without any change, you can read these passed parameters inside your WebService using this code:
[WebMethod]
[ScriptMethod( ResponseFormat = ResponseFormat.Json,
UseHttpGet = true, XmlSerializeString = false)]
public List<PhoneItem> GetJamesBondActors()
{
var test = this.Context.Request.Params["myTest"];
//..
This means that you need to read all your WebService parameters manually and no type control is in here, also your WebService cannot have any parameters by default.
How ASP.NET handles ScriptServices parameters and results
ASP.NET ScriptService is a specific WebService, that has Json formatted paraters and also automatically formats all its results into Json. That is a good advantage, but also requires additional setup in ExtJS.
When you try to change your WebService to accept any paramter, it will automatically expect them encoded as Json and that is not what ExtJS does by default.
ExtJs in the other hand by default passes all its parameters either encoded in Get request as Url parameters, or in the body of the Post request formatted as:
myParam=myParameterValue&mySecondParam=mySecondParameterValue
How to configure ExtJs to pass in Json formatted parameters which ASP.NET ScriptService is expecting ?
First, I did not want to pass my patameters in Json coming as Get patameters and I wanted to Use Post instead.
How to use Post instead of Get in ExtJS called ScriptService
First I need to disable my ScriptService Get method, which I can specify using Attribute UsetHttpGet over the WebMethod:
[WebMethod]
[ScriptMethod( ResponseFormat = ResponseFormat.Json,
UseHttpGet = false, XmlSerializeString = false)]
public List<PhoneItem> GetJamesBondActors(string myTest, string bar) {
// ..
Next step is to setup Ext.data.proxy.Ajax (ExtJS ajax Proxy) action methods to be processed using specified methods (Post), here is my snippet:
proxy: new Ext.data.proxy.Ajax({ //
url: 'WebService1.asmx/GetJamesBondActors',
actionMethods: {
create: 'POST',
destroy: 'DELETE',
read: 'POST',
update: 'POST'
}, // ..
This is all, when you compile your code, you should have all operations excepts the delete using Post.
To pass all your request as Json, I have created an class overriding default Ext.data.proxy.Ajax and I can use this new one instead of this default proxy in my configuration.
/// <reference path="/Scripts/ext-all-debug.js" />
Ext.define('Ext.ux.AspWebAjaxProxy', {
extend: 'Ext.data.proxy.Ajax',
require: 'Ext.data',
buildRequest: function (operation) {
var params = Ext.applyIf(operation.params || {}, this.extraParams || {}),
request;
params = Ext.applyIf(params, this.getParams(params, operation));
if (operation.id && !params.id) {
params.id = operation.id;
}
params = Ext.JSON.encode(params);
request = Ext.create('Ext.data.Request', {
params: params,
action: operation.action,
records: operation.records,
operation: operation,
url: operation.url
});
request.url = this.buildUrl(request);
operation.request = request;
return request;
}
});
Where the important line is "params = Ext.JSON.encode(params);", which will took parameters (either assigned to operation or to the proxy using extraParams and encode them to Json. Whole method is being called each time a request is being created to call Ajax method.
Now my HTML sample for creating ExtJs Grid:
<div id="example-grid"></div>
<asp:ScriptManager ID="PageScriptManager" runat="server">
<Scripts>
<asp:ScriptReference Path="~/Scripts/ext-all-debug.js" />
<asp:ScriptReference Path="~/Scripts/Ext.ux.AspWebAjaxProxy.js" />
</Scripts>
</asp:ScriptManager>
<script type="text/javascript">
Ext.require([
'Ext.grid.*',
'Ext.data.*',
'Ext.panel.*',
'Ext.layout.container.Border'
]);
Ext.namespace('EXT');
Ext.define('Actors', {
extend: 'Ext.data.Model',
fields: ['Name', 'Phone']
});
var store = new Ext.data.Store(
{
proxy: new Ext.ux.AspWebAjaxProxy({ //
url: 'WebService1.asmx/GetJamesBondActors',
actionMethods: {
create: 'POST',
destroy: 'DELETE',
read: 'POST',
update: 'POST'
},
extraParams: {
myTest: 'a',
bar: 'foo'
},
reader: {
type: 'json',
model: 'Actors',
root: 'd'
},
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
})
});
// create the grid
var grid = Ext.create('Ext.grid.Panel', {
store: store,
columns: [
{ text: 'Name', width: 180, dataIndex: 'Name', sortable: true },
{ text: 'Phone', width: 180, dataIndex: 'Phone', sortable: true }
],
renderTo: 'example-grid',
width: 540,
height: 200
});
store.load();
</script>
Now, how does it look my ScriptService:
namespace ExtJSData
{
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class WebService1 : System.Web.Services.WebService
{
public class PhoneItem
{
public string Name;
public string Phone;
}
[WebMethod]
[ScriptMethod( ResponseFormat = ResponseFormat.Json,
UseHttpGet = false, XmlSerializeString = false)]
public List<PhoneItem> GetJamesBondActors(string myTest, string bar)
{
var list = new List<PhoneItem>(new [] {
new PhoneItem() {Name="Sean Connery", Phone="001"},
new PhoneItem() {Name= "Pierce Brosnan",Phone= "002" },
new PhoneItem() {Name= "Daniel Craig",Phone= "003" }
});
return list;
}
}
}
This is all, Sample can be downloaded here