Usage of SignalR and javascript in Acumatica
Today I want to describe how you can use SignalR and javascript in Acumatica. I will describe following functionality:
1. User 1 opens sales order SO006768
2. User 2 opens sales order SO006768
3. User 1 modifies Sales order, and clicks on Save button
4. User 2 gets following notification:
Sales Order: SO006768 was modified.
One of the ways to achieve that, is to use SignalR and a bit of jQuery.
In order to achieve that, following steps are needed:
1. Create interface, which will be a backbone of functionality:
public interface ISalesOrderNotify { Task<string> OrderWasChanged(string refNbr); }
2. Create class, which will bound interface implementation to SignalR of Acumatica:
public class SOOrderHub : Hub<ISalesOrderNotify> { public async Task<string> Notify(string refNbr) { await Clients.Others.OrderWasChanged(refNbr); return await Clients.Caller.OrderWasChanged(refNbr); } }
What I want to specifically highlight, is inheritance from the class Hub, which bounds SignalR with Interface and particular implementation.
3. Inform Acumatica framework about such connection:
public class ServiceRegistration : Module { protected override void Load(ContainerBuilder builder) { builder.RegisterType<SOOrderHub>().ExternallyOwned(); } }
4. And finally, explain in graph or graph extension, how steps 1 - 3 will be used:
public class SOOrderentryExt : PXGraphExtension<SOOrderEntry> { public static bool IsActive() => true; [InjectDependency] internal IConnectionManager SignalRConnectionManager { get; set; } public override void Initialize() { base.Initialize(); var hubContext = GlobalHost.ConnectionManager.GetHubContext<SOOrderHub>(); } [PXOverride] public void Persist(Action basePersist) { basePersist(); var currentOrder = Base.CurrentDocument.Current.RefNbr; var cnt = SignalRConnectionManager.GetHubContext<SOOrderHub>(); cnt.Clients.All.OrderWasChanged(currentOrder); } }
5. In your aspx.cs mention, that you want to have SignalR and jquery:
protected void Page_Init(object sender, EventArgs e) { Master.PopupWidth = 950; Master.PopupHeight = 600; // panel = (PXFormView)this.PanelAddSiteStatus.FindControl("formSitesStatus"); this.ClientScript.RegisterClientScriptInclude(this.GetType(), "jq", VirtualPathUtility.ToAbsolute("~/Scripts/jquery-3.1.1.min.js")); this.ClientScript.RegisterClientScriptInclude(this.GetType(), "jqsr", VirtualPathUtility.ToAbsolute("~/Scripts/jquery.signalR-2.2.1.min.js")); this.ClientScript.RegisterClientScriptInclude(this.GetType(), "hb", VirtualPathUtility.ToAbsolute("~/signalr/hubs")); }
6. In your aspx describe a bit of javascript logic:
<script type="text/javascript"> var hubProxy = $.connection.sOOrderHub; hubProxy.connection.start() .done(function () { console.log("hub proxy started"); } ); hubProxy.on( "OrderWasChanged", function(refNbr) { var value = $("#ctl00_phF_form_t0_edOrderNbr_text").val(); if (value === refNbr) { alert("Sales Order:" + refNbr + " was modified"); } } ); </script>