在FineUI初学手册中提到FineUICoreWebForms
会将页面状态全部回发,后台解析后实现后台得到前台的数据;
之前我还提到过使用SignalR.InvokeAsync来执行js收集前台的信息;
结合以上两点💡,在开发中我使用 FineUICoreMVC
实现了在Controller
中对前端控件状态的获取🛠️,从而减少前台js的代码,让后台方法看起来更加完整📝;
在MVC
中 Controller.cs文件并不能直接⚡️获得前台控件的状态,只能通过前台的收集后回发🔙给后台;在传统的MVC开发中这种方式是被推荐的,具体的方法接收参数,不关心参数值😑的来源,保证了职责的单一性和复用性;这样写也有坏处就是当方法需要接收其他参数时,我需要同时修改提交的js和接收的方法;
其实FineUICore
中的Controller
职责和cshtml
的职责差不多,需要收集和处理前台的信息,最后处理后的信息也是通过响应js来实现的;所以FineUICore
中的Controller
我完全可以考虑负责收集页面📊的数据,让数据的收集和处理统一在一个方法中;
///改进前 [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> OnSaveBtnClick(MsOAR_A1 ms) { awati bll.Save(ms); } ///改进后 public async Task<IActionResult> OnSaveBtnClick() { MsOAR_A1 ms = await Form1.GetData(); awati bll.Save(ms); }
在上面提到过,SignalR.InvokeAsync
可以实时的和前台交互拿到数据,所以没有必要将全部的信息都回发🔄再转为控件模型;可以直接实时拿数据;
理论跑通后我结合现有的框架进行了实践,大致的路径如下
这里需要考虑的问题就是 虽然 SignalR.InvokeAsync
可以执行js 比如 return F.ui.Form1.getdata();
但是这里的SignalR事件监听应该写在哪,这里的Form1
控件明显是在回发的那个页面,执行这段js也应该在这个页面;在框架下可能打开了多个页面,或者弹出的窗口,所以要找到当前回发页面,需要标识;
这里有两个办法,
事件名称
唯一,回发时带着这个事件名称
,后台执行InvokeAsync
时指定事件为事件名称
然后执行js;唯一标识
,并将当前的页面和唯一标识
绑定,当后台执行InvokeAsync
时执行通用的事件,通过唯一标识
找到页面,然后执行js;我选择了第二个方法,这样改动量会小一些;
对于简单的交互,省去了大部分js代码
cshtml.Items( F.Button().ID("btnsave").BtnType(FineUIEx.BtnTypes.保存) .OnClickAsync("OnOARA1Save",autoLoading: "btnsave,btnclear"), F.Button().ID("btnclear").BtnType(FineUIEx.BtnTypes.取消) .Text("清除").OnClickAsync("OnOARA1Delete", autoLoading: "btnsave,btnclear") )),
Controller[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> OnOARA1Save() { //得到数据 var msa1 = await Form1.GetData<MsOAR_A1>(true); if (msa1 != null) { //保存 var rt = await bLLOARA1.Save(msa1); //提示 ShowNotify(Convert.ToInt32(rt.strMsId) >= 0 ? "保存成功" : rt.strMS); //重置ID Form1.SetData(new { OAR_A1_AUTOID = rt.strMsId }, true); //刷新列表 await InitData(); } return ResultAsync(); }
JSHandlewindow.top.PostWindow = {}; //处理fineui的ajax window.top.hub.connection.on(`JSHandle`, async (msg) => { let { postGUID, fun } = JSON.parse(msg); //这里要通过postGUID找到页面 拿到结果后要删除 let page = window.top.PostWindow[postGUID]; let res = (page.Function(fun))(); return res; });
JSHandle//执行JS public static async Task<string> GetHubMessage(string fun) { if (!string.IsNullOrEmpty(fun)) { if (!fun.Trim().StartsWith("return")) { fun = "return " + fun; } //尝试拿一个hubid string evname = "JSHandle"; //本地提交的ID var postGUID = string.Empty; var Form = FineUICore.PageContext.Current.Request.Form; if (Form.ContainsKey("postGUID")) { postGUID = Form["postGUID"]; } //终端ID var id = SignalRHelper.GetHubID(); if (string.IsNullOrEmpty(id) || string.IsNullOrEmpty(postGUID)) { return ""; } var json = JObject.FromObject(new { postGUID, fun }).ToString(); var Hub = PageContext.GetServerByApp<IHubContext<SignalRHub>>(); var msr = await Hub.Clients.Client(id).InvokeAsync<System.Text.Json.JsonElement>(evname, json, new CancellationToken()); return GetValueAsString(msr); } return ""; }
常用的取值,表单值,列表选择行,输入框取值都做了扩展;
FormAjaxExusing FineUICore; namespace HD.UIControl.FineUIBase { public static class FormAjaxEx { /// <summary> /// 得到数据 /// </summary> /// <param name="f"></param> /// <param name="isv">是否验证数据</param> /// <returns></returns> public static async Task<JObject> FGetData(this string f, bool isv = false) { fields ??= Array.Empty<string>(); var fun = $" return F.ui['{f}'].getdata({isv.ToString().ToLower()});"; var res = await FineUIAjaxHelpEx.GetHubMessage(fun); return JToken.Parse(res) is JObject obj ? obj : default; } } }
本文作者:没想好
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!