Ext.net + Sharpkit

  1. #1

    Ext.net + Sharpkit

    Hello
    Sharpkit ( C# -> javascript tool) is pretty silent topic on this forum, I wonder if someone tried to use it in conjuction with Ext.net. In fact, for a while my way of thinking was "ExtJs+Sharpkit" or "Ext.net",so I would not wonder if I'm nearly first trying that. After few weeks of usage "Ext.net + sharpkit" it seems to be pretty powerfull combination for me, so I would like to share my experience and as well if hear any tips in case there is someone who tried that. Note that I'm not "javascript enemy", I'm fine with writing and maintaining js code. But even so the introducing sharpkit opened some nice ways. As well note that I have no relation to Sharpkit company and I was not given anything for writing this post from them.
    So after spending some time in these forums, basic architecture of the application is like "single page app with as much stuff in javascript as possible,where server part providers just a data somehow processed on client side to user controls", single page really means one aspx file. In fact pretty similar to what I would do if I have just ExtJs. That means good-bye to direct events and using just directMethods. In short example

    1) App Structure

    OfficeEdit.ascx:
    <alc:CustomXTypeFormPanel runat="server" CustomInstanceOf="AMS.SharpKit.UserControls.DynamicControls.UserManagement.Maintenance.OfficeEdit">
    	<Items>		<ext:Panel runat="server" Title="Basic Properties" Frame="true" MarginSpec="5" Width="350">
    		<LayoutConfig>
    			<ext:VBoxLayoutConfig />
    		</LayoutConfig>
    		<Items>			 	<alc:TextFieldControl runat="server" ItemID="txtOfficeDesc" FieldLabel="Office" Width="340" AllowBlank="false"/>
    			</Items>
    			<Buttons>
    	<ext:Button runat="server" Text="Save" Icon="Disk" ItemID="btnSave"/>
    			</Buttons>
    		</ext:Panel>
    	</Items>	
    </alc:CustomXTypeFormPanel>
    where CustomXTypeFormPanel is
    public class CustomXTypeFormPanel : FormPanel
    	{
    		public override string XType
    		{
    			get
    			{
    				if (string.IsNullOrEmpty(CustomXType))
    					return CustomInstanceOf.Replace(".", "_");
    				return CustomXType;
    			}
    		}
     
    		public string CustomXType { get; set; }
    		public string CustomInstanceOf { get; set; }
    		public override string InstanceOf
    		{
    			get
    			{
    				return CustomInstanceOf;
    			}
    		}
    	}
    And OfficeEdit js Ext class is smth like
    Ext.define("AMS.SharpKit.UserControls.DynamicControls.UserManagement.Maintenance.OfficeEdit", (function () {
      var publicInterface = {
        extend: "Ext.form.Panel",
        alias: "widget.AMS_SharpKit_UserControls_DynamicControls_UserManagement_Maintenance_OfficeEdit",
        _txtOfficeDesc: null,
        _btnSave: null,
        _btnCancel: null,
        initComponent: function (){
            this.callParent(arguments);
            initializeControls.call(this);
            this._btnCancel.on("click", this.btnCancel_click, this);
            this._btnSave.on("click", this.btnSave_click, this);
        }
    };
    
    // private methods 
    function  btnCancel_click:  (){
            this.fireEvent("tabClose", this);
            this.destroy();
    }
    function  initializeControls:  (){
            this._btnSave = this.down("#btnSave");
            this._txtOfficeDesc = this.down("#txtOfficeDesc");
            this._btnCancel = this.down("#btnCancel");
    }
    function  btnSave_click(){
            if (this.getForm().isValid() == false){
                Ext.MessageBox.alert("Validation Failed", "Validation has failed, please correct highlighted fields");
                return;
            }
            var dto = {
                OfficeID: this._data.OfficeId,
                OfficeDesc: this._txtOfficeDesc.getValue()
            };
            Ext.net.DirectMethods.UserManagement_SaveOffice.callAjax(dto, {
                target: this,
                success:  this.save_success,
    	  scope:this
            });
        }
    
         
    ...
        return publicInterface;
    })());
    }
    Note that callAjax is a simple javascript helper that shows "Show loading..." mask on target while ext request is executed

    and the ascx is translated to javascript usign simple trick like

    ...
    UserControl ctrl = (UserControl)LoadControl("~/OfficeEdit");
    var jsConfig = ComponentLoader.ToConfig(ctrl, false);
    scripts.AppendFormat("AMS.Data.scripts.{0} = {1};", "officeEdit", JSON.Serialize(jsConfig));
    ...

    So to say above in few words - UI is created using ascx files UI behavior code in parent Ext javascript class, technically there is technological separation between user interface and its functionality.

    2) Sharpkit to the game

    So now sharpkit comes to game, it's place is to replace OfficeEdit.js with C# code. Furtunatelly there is relativelly nice support in sharpkit for ExtJS, so start is pretty straightfoward:
    [JsType(JsMode.ExtJs, InlineFields = true)]
    public class UserEdit : Ext.form.Panel
    {
         public string alias = "widget.AMS_SharpKit_UserControls_DynamicControls_UserManagement_UserEdit";
    }
    note that InlineFields attribute is now the only way how to have alias generated on the right place in extjs class definition (and it's picked later on by ascx result code so we need it)
    next overriding of the initComponent

    protected override void initComponent()
    {
         this.callParent(@arguments);
        //base.initComponent();
     
        _initializeControls();
     
         this._btnCancel.on("click", new JsNativeAction(_btnCancel_click), this);
         this._btnSave.on("click",new JsNativeAction(_btnSave_click),this);
    }
    There are few notes around this
    a) see that base C# code is replaced by "ExtJs callparent", this is bit confusing and so far must be done, otherwise different js code would be generated
    b) initializeControls is with underscore. Reason here is that all C# methods are generated as public ExtJs methods (see that in javascript snippet above most of "methods" are private). so the question is how to face that. Problem is that I'm not aware of any "official pattern" for private methods for ExtJS 4.x, so can hardly ask Sharpkit guys to support it somehow. This will change with ExtJs 5. But from the other side - does it really matter? Sharkit methods are called by C# code 99% of time, and here encaspulation is set of course checked properly
    c) so far its impossible to write this._btnCancel.click += btnCancel_click
    Good new is that it can be fixed in future as for custom controls (mean those I define myself) it is possible.

    3) cancel click and custom event

    cancel click does not do anything interesting then
    private void _btnCancel_click() {
     	fireEvent("tabClose",this);
    	this.destroy();
    }
    the C# definition of the event is more interesting:
    public event JsNativeAction<UserEdit> tabClose
    		{
    			[JsMethod(Name = "on", InsertArg0 = "'tabClose'", InsertArg2 = "this", Export = false)] add
    			{
    				
    			}
    			[JsMethod(Name = "un", InsertArg0 = "'tabClose'", Export = false)] remove
    			{
    			}
    	}
    the attribute purpose here is to enable handling even in C# way while genereting code in "javascript way"

    so in C#
    userEdit.tabClose += delegate(UserEdit edit)
    {
    									 edit.close();
    };
    results javascript
    userEdit.on('tabClose', function (edit){
                edit.close();
            }, this);
    I think it's pretty nice demostration of Sharpkit power - it's not a just blind convertor from one laguage to another but allows plenty of customization.


    4) Initialize controls and As operator


    private void _initializeControls()
    		{
    			_btnSave = this.down("#btnSave").As<Button>();
     
    			_txtOfficeDesc = this.down("#txtOfficeDesc").As<TextFieldControl>();
    			_btnCancel = this.down("#btnCancel").As<Button>();
     
     
    		}
    You can see .As operator usage. In fact , nativelly I tried to use cast operator, which does not work (at least generated some strange javascript). Simply answer to all the problems is "use AS" operator when chaning type in Sharpkit. that's one of things to remember)

    5) Save implementation and Direct methods call

    private void btnSave_click()
    		{
    			if (this.getForm().isValid() == false)
    			{
    				Ext.MessageBox.alert("Validation Failed", "Validation has failed, please correct highlighted fields");
    				return;
    			}
    			var dto = new OfficeEditDTO
    			{
    				
    				OfficeID = _data.OfficeId,
    				OfficeDesc = _txtOfficeDesc.text
    			};
     
    			/* 
    			  here I want to have :
    			          Ext.net.DirectMethods.UserManagement_SaveOffice.callAjax(dto, {
    					    target: this,
    						success:  this.save_success,
    						scope:this
                                        });
    			 */
    		}
    Begining of method is pretty straigfoward, now the question is what to do with direct methods. Here maybe some of you give me better ideas as my solution is bit ... crazy

    so I have the server method like (first improvement would be probably to use MVC controller but practically I didn't find any way how it would help)
    [DirectMethod(RethrowException = true)]
    public static int UserManagement_SaveOffice(OfficeEditDTO dto)
    {		return ServiceLocator.Get<UserManagementMaintenance>().SaveOffice(dto);
    }
    and on Sharpkit I would like to call it as
    OfficeEditDTO dto = ...
    UserManagementDirectMethods.SaveOffice(dto, new AjaxParameter<int>
    {
    	target = this,
    	success = save_success
    });
    and in javascript generated as

            Ext.net.DirectMethods.UserManagement_SaveOffice.callAjax(dto, {
                target: this,
                success:  this.save_success,
    	  scope:this
            });
    relativelly confusing task, here is my solution
    a) OfficeEditDTO (means any dto used on both sides of game) is created in separate library and make available for sharpkit
    (you can see that it is used in Sharkit code as well as on the server code)
    [JsType(JsMode.Json)]
    	public class OfficeEditDTO
    	{
    		public int? OfficeID { get; set; }
    		public string OfficeDesc { get; set; }
    	}
    It's marked as JSON type as that the way how Sharkit does not generate getter and setter when setting/getting it's properties

    so that way I get type safety for the direct method parameters

    b) I need one "intermediate" class that would transform the js call. I was trying to play with attributes of direct method in order to generate right javascript originally, but as number of parameters is different in both methods I didn't find a way how to make it work. So I add this to the sharkit side of project
    [JsType(JsMode.Json)]
    	public class AjaxParameter
    	{
    		public JsAction success { get; set; }
    		public Object target { get; set; }
    	}
     
    	[JsType(JsMode.Prototype, Name = "Ext.net.DirectMethods", Export = false)]
    	public class UserManagementDirectMethods
    	{
    	          [JsMethod(Name = "UserManagement_SaveOffice.callAjax")]
    		public static int SaveOffice(OfficeEditDTO dto, AjaxParameter<int> args = null)
    		{
    			return 0;
    		}
                     }
    See again that Export=false + Name attribute do the trick how to achieve desired code.
    Having this class is little annoying overhead, but as long as I don't find better solution I think it could be generated during the build usign reflection from the directmethods

    6) save_success handler and the "dummy" helpers

    this is desired code:
    Ext.net.Notification.show({
    			iconCls: 'icon-information',
    			pinEvent: 'click',
    			html: 'Save done',
    			hideDelay: 5000,
    			title: title
    		});
    obviously there is a problem - Sharpkit support so far ExtJs, not Ext.net. Sittindg down and writing a support for ext.nt is probably not the fastest idea, so "kind of dummy" classes comes into the game
    in js I have:
    AMS.Helpers = function () {
    function showAMSTip(title, msg) {
    		
    
    		Ext.net.Notification.show({
    			iconCls: 'icon-information',
    			pinEvent: 'click',
    			html: msg,
    			hideDelay: 5000,
    			title: title
    		});
    	}
    on sharpkit then
     [JsType(JsMode.Prototype,Name="helpers", Export = false)]
        public static class helpers
        {
    	   public static void showAMSTip(string title, string message){}
        }
    which as a result allows me to write
    private void save_success(int officeId)
    		{		
    	helpers.showAMSTip("Save Succesfull", string.Format("Office {0} has been saved", _txtOfficeDesc.text));
    		}
    pretty nice no? So far this trick worked for any "missing" functionality in Sharkpit and even more it forced me to extract the pieces I really need to helper methods. Note that I was given source code of sharpkit SDK, so I can really modify that and add Ext.Net support.

    7) summary:

    - I have my views in ascx (the same could be done in razor or so, I just like ascx files, in fact more then sencha architect)
    - I have me javascript code in C#, the only js code I wrote is in "dummy" class helpers

    All the features like refactoring and so then works - intelisence, resharper etc - works like a charm.
    Practically I don't see myself productivity dramaticlly changing ith sharpkit, at least not now. Using sharpkit is bit more verbose, so I'm writing more code then before. But the benefit I spot here is less time in silly js bugs as once C# become compilable the js is correct.
    I was thinking to use ExtJs + Sharpkit + sencha architect before and in fact I did similar excercise with that combination like the one above. Of course that's powerfull combination too, but the problem with that is
    a) bit harder to stick sharkit scripts to the code generated by architect, basically architect responsibility are just views that require inheritance, which require working with two tools and switching here and back (of course sometimes that could be considerable advantage depending on team structure) and later on picking the architect scipts somehow
    b) Ext.net has bit more features then ExtJs and I was missing those
    c) At the end of the day I didn't find mysef slower with UI in ascx

    To be fair there are some disadvantages of using sharkit as well
    a) It cost something ( for project I'm working on it's price does not worth mentioning but definitelly it's not free for commercial usage)
    b) ExtJS wrapper was autogenerated and contains some bugs - for example Observable is interface (what?) and so
    c) There are some pieces that is good to remember ( like As operator above), but definitelly learning curve here is significantly faster then for whole ExtJs
    d) documentation of Sharpkit is pretty poor. Well - A lot of stuff is traightwofard, but some managers ( and not only them) does not tust to projects like that. In fact my impression is that whole Sharpkit project is managed by 1-2 people ( so will it silently disappear one day? who knows...)

    Any comments welcome
    Zdenek
  2. #2
    Hi @Zdenek,

    Thank you for the such a detailed post. We will investigate.
  3. #3
    Hello @Zdenek,

    We were working on something very-very-very related to your post. You might be interested to read this post:
    http://forums.ext.net/showthread.php...Bridge-Is-Open
  4. #4
    Yes, I got announcement email this morning

    One that I don't understand - does Bridge have Ext JS ( or even better Ext.NET support?)

    Does not seems so and it is not as well listed in coming soon....
    Last edited by geoffrey.mcgill; Mar 31, 2015 at 6:54 PM.
  5. #5
    Unfortunately, there is no specific support for Ext.NET.

    ExtJS and Ext.NET cannot be open source, but Bridge.NET is open source. It is the biggest issue with that. We cannot plan Ext.NET and ExtJS support because of that issue.
  6. #6
    OK
    probably academic discussion - but what exactly is the issue here?
    Bridge.NET could be - like a sharpkit) - just a bridge - so it allow you to generate javascript (as open source) using C# but it does not allow you to use it together with extnet/extjs

    I would understand arguments like "ExtJs is big library,creating and maintaining C# counterpart is difficult" or something like that, but why arguing with "open source" ?

    Z
  7. #7
    I would understand arguments like "ExtJs is big library,creating and maintaining C# counterpart is difficult" or something like that
    Yes, it is also a big problem with that.

    but why arguing with "open source" ?
    Maybe, I misunderstand something here. I'll ask my colleague who is much more experienced in licensing than I am.
    Last edited by Daniil; Apr 01, 2015 at 8:37 AM.
  8. #8
    OK
    probably academic discussion - but what exactly is the issue here?
    Bridge.NET could be - like a sharpkit) - just a bridge - so it allow you to generate javascript (as open source) using C# but it does not allow you to use it together with extnet/extjs

    I would understand arguments like "ExtJs is big library,creating and maintaining C# counterpart is difficult" or something like that, but why arguing with "open source" ?

    Z
    The Sencha Ext JS commercial licensing explicitly prohibits projects like Bridge.NET from creating adapters, "bridge" projects or toolkits.

    At face value, SharpKit's implementation of the Ext JS bridge is a violation of the Sencha Software License Agreement. Unless of course SharpKit has an OEM agreement with Sencha for this use, which I suspect not. That would also mean any projects using the SharpKit Ext JS implementation are in violation of the Sencha License Agreement. Maybe there's an OEM agreement in place, but I'm unaware of its existence.

    Here's the specific section from the License Agreement:

    4. PROHIBITED USES

    You may not redistribute the Software or Modifications other than by including the Software or a portion thereof within Your Application. You may not redistribute the Software or Modifications as part of any Application that can be described as a development toolkit or library, an application builder, a website builder or any Application that is intended for use by software, application, or website developers or designers.
    Ext.NET does have an official OEM agreement in place with Sencha, so everything is cool on that front.

    For Bridge.NET our focus is on supporting the open-source community and open-source projects first. How Bridge integrates with Ext.NET has always been a little uncertain. At this point... it doesn't.
    Last edited by geoffrey.mcgill; Mar 31, 2015 at 8:57 PM.
    Geoffrey McGill
    Founder

Tags for this Thread

Posting Permissions