예제 #1
0
        public async Task Server(String command, String baseUrl, Int64 userId, HttpResponseBase response)
        {
            var rm = await RequestModel.CreateFromBaseUrl(_host, Admin, baseUrl);

            RequestView rw       = rm.GetCurrentAction();
            String      loadProc = rw.LoadProcedure;

            if (loadProc == null)
            {
                throw new RequestModelException("The data model is empty");
            }
            var prms = new ExpandoObject();

            prms.Set("UserId", userId);
            prms.Set("Id", rw.Id);
            IDataModel model = await _dbContext.LoadModelAsync(rw.CurrentSource, loadProc, prms);

            var msi = new ModelScriptInfo()
            {
                DataModel = model,
                Template  = rw.template,
                Path      = rw.Path
            };
            var ss = _scripter.GetServerScript(msi);

            response.ContentType = "text/javascript";
            response.Write(ss.Script);
        }
예제 #2
0
        internal async Task SaveDataObj(Action <ExpandoObject> setParams, ExpandoObject dataToSave, TextWriter writer)
        {
            String baseUrl = dataToSave.Get <String>("baseUrl");

            if (NormalizeBaseUrl != null)
            {
                baseUrl = NormalizeBaseUrl(baseUrl);
            }
            ExpandoObject data = dataToSave.Get <ExpandoObject>("data");
            var           rm   = await RequestModel.CreateFromBaseUrl(_host, Admin, baseUrl);

            RequestView rw   = rm.GetCurrentAction();
            var         prms = new ExpandoObject();

            setParams?.Invoke(prms);
            prms.Append(rw.parameters);
            CheckUserState(prms);
            IDataModel model = await _dbContext.SaveModelAsync(rw.CurrentSource, rw.UpdateProcedure, data, prms);

            IModelHandler handler = rw.GetHookHandler();

            if (handler != null)
            {
                await handler.AfterSave(data, model.Root);
            }
            WriteDataModel(model, writer);
        }
예제 #3
0
        internal async Task ReloadData(Action <ExpandoObject> setParams, String json, TextWriter writer)
        {
            ExpandoObject dataToSave = JsonConvert.DeserializeObject <ExpandoObject>(json, new ExpandoObjectConverter());
            String        baseUrl    = dataToSave.Get <String>("baseUrl");

            ExpandoObject loadPrms = new ExpandoObject();

            if (baseUrl.Contains("?"))
            {
                var parts = baseUrl.Split('?');
                baseUrl = parts[0];
                // parts[1] contains query parameters
                var qryParams = HttpUtility.ParseQueryString(parts[1]);
                loadPrms.Append(CheckPeriod(qryParams), toPascalCase: true);
            }

            if (NormalizeBaseUrl != null)
            {
                baseUrl = NormalizeBaseUrl(baseUrl);
            }

            if (baseUrl == null)
            {
                throw new RequestModelException("There are not base url for command 'reload'");
            }

            var rm = await RequestModel.CreateFromBaseUrl(_host, Admin, baseUrl);

            RequestView rw       = rm.GetCurrentAction();
            String      loadProc = rw.LoadProcedure;

            if (loadProc == null)
            {
                throw new RequestModelException("The data model is empty");
            }
            setParams?.Invoke(loadPrms);
            loadPrms.Set("Id", rw.Id);
            loadPrms.Append(rw.parameters);
            ExpandoObject prms2 = loadPrms;

            if (rw.indirect)
            {
                // for indirect action - @UserId and @Id only
                prms2 = new ExpandoObject();
                setParams?.Invoke(prms2);
                prms2.Set("Id", rw.Id);
            }
            IDataModel model = await _dbContext.LoadModelAsync(rw.CurrentSource, loadProc, prms2);

            if (rw.HasMerge)
            {
                var mergeModel = await _dbContext.LoadModelAsync(rw.MergeSource, rw.MergeLoadProcedure, prms2);

                model.Merge(mergeModel);
            }
            rw = await LoadIndirect(rw, model, loadPrms);

            WriteDataModel(model, writer);
        }
예제 #4
0
        public async Task RenderElementKind(RequestUrlKind kind, String pathInfo, ExpandoObject loadPrms, TextWriter writer)
        {
            RequestModel rm = await RequestModel.CreateFromUrl(_host, Admin, kind, pathInfo);

            RequestView rw = rm.GetCurrentAction(kind);

            await Render(rw, writer, loadPrms);
        }
예제 #5
0
        async Task <RequestView> LoadIndirect(RequestView rw, IDataModel innerModel, ExpandoObject loadPrms)
        {
            if (!rw.indirect)
            {
                return(rw);
            }
            if (!String.IsNullOrEmpty(rw.target))
            {
                String targetUrl = innerModel.Root.Resolve(rw.target);
                if (String.IsNullOrEmpty(rw.targetId))
                {
                    throw new RequestModelException("targetId must be specified for indirect action");
                }
                targetUrl += "/" + innerModel.Root.Resolve(rw.targetId);
                var rm = await RequestModel.CreateFromUrl(_host, Admin, rw.CurrentKind, targetUrl);

                rw = rm.GetCurrentAction();
                String loadProc = rw.LoadProcedure;
                if (loadProc != null)
                {
                    loadPrms.Set("Id", rw.Id);
                    var newModel = await _dbContext.LoadModelAsync(rw.CurrentSource, loadProc, loadPrms);

                    innerModel.Merge(newModel);
                    innerModel.System.Set("__indirectUrl__", rm.BaseUrl);
                }
            }
            else
            {
                // simple view/model redirect
                if (rw.targetModel == null)
                {
                    throw new RequestModelException("'targetModel' must be specified for indirect action without 'target' property");
                }
                rw.model      = innerModel.Root.Resolve(rw.targetModel.model);
                rw.view       = innerModel.Root.Resolve(rw.targetModel.view);
                rw.viewMobile = innerModel.Root.Resolve(rw.targetModel.viewMobile);
                rw.schema     = innerModel.Root.Resolve(rw.targetModel.schema);
                if (String.IsNullOrEmpty(rw.schema))
                {
                    rw.schema = null;
                }
                rw.template = innerModel.Root.Resolve(rw.targetModel.template);
                if (String.IsNullOrEmpty(rw.template))
                {
                    rw.template = null;
                }
                String loadProc = rw.LoadProcedure;
                if (loadProc != null)
                {
                    loadPrms.Set("Id", rw.Id);
                    var newModel = await _dbContext.LoadModelAsync(rw.CurrentSource, loadProc, loadPrms);

                    innerModel.Merge(newModel);
                }
            }
            return(rw);
        }
예제 #6
0
        public async Task RenderElementKind(RequestUrlKind kind, String pathInfo, ExpandoObject loadPrms, TextWriter writer)
        {
            RequestModel rm = await RequestModel.CreateFromUrl(_host, kind, pathInfo);

            RequestView rw = rm.GetCurrentAction(kind);

            rw.CheckPermissions(_userStateManager?.GetUserPermissions(), Host.IsDebugConfiguration);
            await Render(rw, writer, loadPrms);
        }
예제 #7
0
        public async Task RenderModel(String pathInfo, ExpandoObject loadPrms, TextWriter writer)
        {
            RequestModel rm = await RequestModel.CreateFromUrl(_host, Admin, RequestUrlKind.Page, pathInfo);

            RequestView rw = rm.GetCurrentAction(RequestUrlKind.Page);

            rw.view = NO_VIEW;             // no view here
            await Render(rw, writer, loadPrms);
        }
예제 #8
0
        internal async Task SaveDataObj(Action <ExpandoObject> setParams, ExpandoObject dataToSave, TextWriter writer)
        {
            String baseUrl = dataToSave.Get <String>("baseUrl");

            if (NormalizeBaseUrl != null)
            {
                baseUrl = NormalizeBaseUrl(baseUrl);
            }
            ExpandoObject data = dataToSave.Get <ExpandoObject>("data");
            var           rm   = await RequestModel.CreateFromBaseUrl(_host, baseUrl);

            RequestView rw   = rm.GetCurrentAction();
            var         prms = new ExpandoObject();

            setParams?.Invoke(prms);
            prms.Append(rw.parameters);
            CheckUserState(prms);
            IDataModel model = null;

            IModelHandler handler      = rw.GetHookHandler();
            String        invokeTarget = rw.GetInvokeTarget();

            if (handler != null)
            {
                Int64 userId  = prms.Get <Int64>("UserId");
                var   handled = await handler.BeforeSave(userId, data);

                if (!handled)
                {
                    model = await _dbContext.SaveModelAsync(rw.CurrentSource, rw.UpdateProcedure, data, prms);

                    await handler.AfterSave(userId, data, model.Root);
                }
            }
            else if (invokeTarget != null)
            {
                model = await _dbContext.SaveModelAsync(rw.CurrentSource, rw.UpdateProcedure, data, prms);

                var clr = new ClrInvoker();
                clr.EnableThrow();
                clr.Invoke(invokeTarget, prms);                 // after save
            }
            else
            {
                model = await _dbContext.SaveModelAsync(rw.CurrentSource, rw.UpdateProcedure, data, prms);
            }
            var eh = rw?.events?.afterSave;

            if (eh != null)
            {
                // new model data
                await _dbContext.SaveModelAsync(eh.CurrentSource(rw), eh.UpdateProcedure(rw), model.Root, prms);
            }
            WriteDataModel(model, writer);
        }
예제 #9
0
        async Task <String> WriteModelScriptModel(RequestView rw, IDataModel model, String rootId)
        {
            StringBuilder output        = new StringBuilder();
            String        dataModelText = "null";
            String        templateText  = "{}";
            StringBuilder sbRequired    = new StringBuilder();

            if (model != null)
            {
                // write model script
                String fileTemplateText = null;
                if (rw.template != null)
                {
                    fileTemplateText = await _host.ReadTextFile(Admin, rw.Path, rw.template + ".js");

                    AddRequiredModules(sbRequired, fileTemplateText);
                    templateText = CreateTemplateForWrite(_localizer.Localize(null, fileTemplateText));
                }
                dataModelText = JsonConvert.SerializeObject(model.Root, StandardSerializerSettings);
            }

            const String scriptText =
                @"
'use strict';
window.$currentModule = function() {
	$(RequiredModules)


	$(ModelScript)

	const rawData = $(DataModelText);
	const template = $(TemplateText);
	return {
		dataModel: modelData(template, rawData)
	};
};";
            const String emptyModel = "function modelData() {return null;}";
            var          text       = new StringBuilder(scriptText);

            text.Replace("$(DataModelText)", dataModelText);
            text.Replace("$(TemplateText)", _localizer.Localize(null, templateText));
            text.Replace("$(RequiredModules)", sbRequired != null ? sbRequired.ToString() : String.Empty);
            String modelScript = model != null?model.CreateScript(_scripter) : emptyModel;

            text.Replace("$(ModelScript)", modelScript);
            output.Append(text);
            return(output.ToString());
        }
예제 #10
0
        protected internal async Task Render(RequestView rwArg, TextWriter writer, ExpandoObject loadPrms, Boolean secondPhase = false)
        {
            var dmAndView = await GetDataModelForView(rwArg, loadPrms);

            IDataModel model = dmAndView.Model;
            var        rw    = dmAndView.RequestView;

            String rootId = "el" + Guid.NewGuid().ToString();

            if (_renderer == null)
            {
                throw new InvalidOperationException("Service 'IRenderer' not registered");
            }

            var msi = new ModelScriptInfo()
            {
                DataModel = model,
                RootId    = rootId,
                IsDialog  = rw.IsDialog,
                Template  = rw.template,
                Path      = rw.Path,
                BaseUrl   = rw.ParentModel.BasePath
            };
            var si = await _scripter.GetModelScript(msi);

            String modelScript = si.Script;
            // TODO: use view engines
            // try xaml
            String fileName = rw.GetView() + ".xaml";
            String basePath = rw.ParentModel.BasePath;

            String filePath = _host.ApplicationReader.MakeFullPath(rw.Path, fileName);

            Boolean bRendered = false;

            if (_host.ApplicationReader.FileExists(filePath))
            {
                // render XAML
                using (var strWriter = new StringWriter())
                {
                    var ri = new RenderInfo()
                    {
                        RootId               = rootId,
                        FileName             = filePath,
                        FileTitle            = fileName,
                        Path                 = basePath,
                        Writer               = strWriter,
                        DataModel            = model,
                        Localizer            = _localizer,
                        CurrentLocale        = null,
                        IsDebugConfiguration = _host.IsDebugConfiguration,
                        SecondPhase          = secondPhase
                    };
                    _renderer.Render(ri);
                    // write markup
                    writer.Write(strWriter.ToString());
                    bRendered = true;
                }
            }
            else
            {
                // try html
                fileName = rw.GetView() + ".html";
                filePath = _host.ApplicationReader.MakeFullPath(rw.Path, fileName);
                if (_host.ApplicationReader.FileExists(filePath))
                {
                    using (_host.Profiler.CurrentRequest.Start(ProfileAction.Render, $"render: {fileName}"))
                    {
                        using (var tr = new StreamReader(filePath))
                        {
                            String htmlText = await tr.ReadToEndAsync();

                            htmlText = htmlText.Replace("$(RootId)", rootId);
                            writer.Write(htmlText);
                            bRendered = true;
                        }
                    }
                }
            }
            if (!bRendered)
            {
                throw new RequestModelException($"The view '{rw.GetView()}' was not found. The following locations were searched:\n{rw.GetRelativePath(".xaml")}\n{rw.GetRelativePath(".html")}");
            }
            writer.Write(modelScript);
        }
예제 #11
0
        internal async Task <DataModelAndView> GetDataModelForView(RequestView rw, ExpandoObject loadPrms)
        {
            var dmv = new DataModelAndView()
            {
                RequestView = rw
            };
            String     loadProc = rw.LoadProcedure;
            IDataModel model    = null;

            if (rw.parameters != null && loadPrms == null)
            {
                loadPrms = rw.parameters;
            }
            if (loadPrms != null)
            {
                loadPrms.AppendIfNotExists(rw.parameters);
                if (rw.Id != null)
                {
                    loadPrms.Set("Id", rw.Id);
                }
            }
            if (loadProc != null)
            {
                ExpandoObject prms2 = loadPrms;
                if (rw.indirect)
                {
                    // for indirect - @TenantId, @UserId and @Id only
                    prms2 = new ExpandoObject();
                    prms2.Set("Id", rw.Id);
                    if (loadPrms != null)
                    {
                        prms2.Set("UserId", loadPrms.Get <Int64>("UserId"));
                        prms2.Set("TenantId", loadPrms.Get <Int32>("TenantId"));
                    }
                }
                model = await _dbContext.LoadModelAsync(rw.CurrentSource, loadProc, prms2);

                if (rw.copy)
                {
                    model.MakeCopy();
                }
                if (!String.IsNullOrEmpty(rw.Id) && !rw.copy)
                {
                    var me = model.MainElement;
                    if (me.Metadata != null)
                    {
                        var modelId = me.Id ?? String.Empty;
                        if (rw.Id != modelId.ToString())
                        {
                            throw new RequestModelException($"Element not found. Id={rw.Id}");
                        }
                    }
                }
            }
            if (rw.indirect)
            {
                rw = await LoadIndirect(rw, model, loadPrms);
            }
            if (model?.Root != null)
            {
                // side effect!
                rw.view     = model.Root.Resolve(rw.view);
                rw.template = model.Root.Resolve(rw.template);
            }

            if (_userStateManager != null && model != null)
            {
                Int64 userId = loadPrms.Get <Int64>("UserId");
                if (_userStateManager.IsReadOnly(userId))
                {
                    model.SetReadOnly();
                }
            }
            dmv.Model       = model;
            dmv.RequestView = rw;
            return(dmv);
        }
예제 #12
0
        internal async Task <DataModelAndView> GetDataModelForView(RequestView rw, ExpandoObject initialParams)
        {
            var dmv = new DataModelAndView()
            {
                RequestView = rw
            };
            String loadProc = rw.LoadProcedure;


            // real params = [model.json, id, initial]
            var realParams = new ExpandoObject();

            realParams.Append(rw.parameters);
            if (rw.Id != null)
            {
                realParams.Set("Id", rw.Id);
            }
            realParams.Append(initialParams);

            IDataModel model = null;

            if (loadProc != null)
            {
                ExpandoObject prms2 = realParams;
                if (rw.indirect)
                {
                    // for indirect - @TenantId, @UserId and @Id only
                    prms2 = new ExpandoObject();
                    prms2.Set("Id", rw.Id);
                    if (realParams != null)
                    {
                        prms2.Set("UserId", realParams.Get <Int64>("UserId"));
                        prms2.Set("TenantId", realParams.Get <Int32>("TenantId"));
                    }
                }
                model = await _dbContext.LoadModelAsync(rw.CurrentSource, loadProc, prms2, rw.commandTimeout);

                if (rw.HasMerge)
                {
                    var mergeModel = await _dbContext.LoadModelAsync(rw.MergeSource, rw.MergeLoadProcedure, prms2, rw.commandTimeout);

                    model.Merge(mergeModel);
                }
                if (rw.copy)
                {
                    model.MakeCopy();
                }
                if (!String.IsNullOrEmpty(rw.Id) && !rw.copy)
                {
                    var me = model.MainElement;
                    if (me.Metadata != null)
                    {
                        var modelId = me.Id ?? String.Empty;
                        if (rw.Id != modelId.ToString())
                        {
                            throw new RequestModelException($"Element not found. Id={rw.Id}");
                        }
                    }
                }
            }
            if (rw.indirect)
            {
                rw = await LoadIndirect(rw, model, realParams);
            }
            if (model?.Root != null)
            {
                // side effect!
                rw.view       = model.Root.Resolve(rw.view);
                rw.viewMobile = model.Root.Resolve(rw.viewMobile);
                rw.template   = model.Root.Resolve(rw.template);
                rw.checkTypes = model.Root.Resolve(rw.checkTypes);
            }

            if (_userStateManager != null && model != null)
            {
                Int64 userId = realParams.Get <Int64>("UserId");
                if (_userStateManager.IsReadOnly(userId))
                {
                    model.SetReadOnly();
                }
            }
            dmv.Model       = model;
            dmv.RequestView = rw;
            return(dmv);
        }
예제 #13
0
        async Task <String> WriteModelScript(RequestView rw, IDataModel model, String rootId)
        {
            StringBuilder output        = new StringBuilder();
            String        dataModelText = "{}";
            String        templateText  = "{}";
            StringBuilder sbRequired    = new StringBuilder();
            // write model script
            String fileTemplateText = null;

            if (rw.template != null)
            {
                fileTemplateText = await _host.ReadTextFile(Admin, rw.Path, rw.template + ".js");

                AddRequiredModules(sbRequired, fileTemplateText);
                templateText = CreateTemplateForWrite(_localizer.Localize(null, fileTemplateText));
            }
            if (model != null)
            {
                dataModelText = JsonConvert.SerializeObject(model.Root, StandardSerializerSettings);
            }


            const String scriptHeader =
                @"
<script type=""text/javascript"">

'use strict';

$(RequiredModules)

(function() {
	const DataModelController = component('baseController');

	const utils = require('std:utils');
	const uPeriod = require('std:period');

	const rawData = $(DataModelText);
	const template = $(TemplateText);
";
            const String scriptFooter =
                @"
const vm = new DataModelController({
	el:'#$(RootId)',
	props: {
		inDialog: {type: Boolean, default: $(IsDialog)},
		pageTitle: {type: String}
	},
	data: modelData(template, rawData),
	computed: {
		utils() { return utils; },
		period() { return uPeriod; }
	},
});

	vm.$data._host_ = {
		$viewModel: vm
	};

	vm.__doInit__();

})();
</script>
";
            var header = new StringBuilder(scriptHeader);

            header.Replace("$(RootId)", rootId);
            header.Replace("$(DataModelText)", dataModelText);
            header.Replace("$(TemplateText)", _localizer.Localize(null, templateText));
            header.Replace("$(RequiredModules)", sbRequired != null ? sbRequired.ToString() : String.Empty);
            output.Append(header);
            if (model != null)
            {
                output.Append(model.CreateScript(_scripter));
            }
            else
            {
                output.Append(_scripter.CreateEmptyStript());
            }
            var footer = new StringBuilder(scriptFooter);

            footer.Replace("$(RootId)", rootId);
            footer.Replace("$(IsDialog)", rw.IsDialog.ToString().ToLowerInvariant());
            output.Append(footer);
            return(output.ToString());
        }
예제 #14
0
        protected async Task Render(RequestView rw, TextWriter writer, ExpandoObject loadPrms)
        {
            String     loadProc = rw.LoadProcedure;
            IDataModel model    = null;

            if (rw.parameters != null && loadPrms == null)
            {
                loadPrms = rw.parameters;
            }
            if (loadPrms != null)
            {
                loadPrms.Set("Id", rw.Id);
                loadPrms.AppendAndReplace(rw.parameters);
            }
            if (loadProc != null)
            {
                ExpandoObject prms2 = loadPrms;
                if (rw.indirect)
                {
                    // for indirect - @TenantId, @UserId and @Id only
                    prms2 = new ExpandoObject();
                    prms2.Set("Id", rw.Id);
                    if (loadPrms != null)
                    {
                        prms2.Set("UserId", loadPrms.Get <Int64>("UserId"));
                        prms2.Set("TenantId", loadPrms.Get <Int32>("TenantId"));
                    }
                }
                model = await _dbContext.LoadModelAsync(rw.CurrentSource, loadProc, prms2);

                if (!String.IsNullOrEmpty(rw.Id))
                {
                    var modelId = model.FirstElementId ?? String.Empty;
                    if (rw.Id != modelId.ToString())
                    {
                        throw new RequestModelException($"Element not found. Id={rw.Id}");
                    }
                }
            }
            if (rw.indirect)
            {
                rw = await LoadIndirect(rw, model, loadPrms);
            }

            if (_userStateManager != null && model != null)
            {
                Int64 userId = loadPrms.Get <Int64>("UserId");
                if (_userStateManager.IsReadOnly(userId))
                {
                    model.SetReadOnly();
                }
            }

            String rootId      = "el" + Guid.NewGuid().ToString();
            String modelScript = null;

            String viewName = rw.GetView();

            if (viewName == NO_VIEW)
            {
                modelScript = await WriteModelScriptModel(rw, model, rootId);

                writer.Write(modelScript);
                return;
            }

            if (_renderer == null)
            {
                throw new InvalidOperationException("Service 'IRenderer' not registered");
            }

            modelScript = await WriteModelScript(rw, model, rootId);

            // TODO: use view engines
            // try xaml
            String  fileName  = rw.GetView() + ".xaml";
            String  filePath  = _host.MakeFullPath(Admin, rw.Path, fileName);
            Boolean bRendered = false;

            if (System.IO.File.Exists(filePath))
            {
                // render XAML
                if (System.IO.File.Exists(filePath))
                {
                    using (var strWriter = new StringWriter())
                    {
                        var ri = new RenderInfo()
                        {
                            RootId               = rootId,
                            FileName             = filePath,
                            FileTitle            = fileName,
                            Writer               = strWriter,
                            DataModel            = model,
                            Localizer            = _localizer,
                            CurrentLocale        = null,
                            IsDebugConfiguration = _host.IsDebugConfiguration
                        };
                        _renderer.Render(ri);
                        // write markup
                        writer.Write(strWriter.ToString());
                        bRendered = true;
                    }
                }
            }
            else
            {
                // try html
                fileName = rw.GetView() + ".html";
                filePath = _host.MakeFullPath(Admin, rw.Path, fileName);
                if (System.IO.File.Exists(filePath))
                {
                    using (_host.Profiler.CurrentRequest.Start(ProfileAction.Render, $"render: {fileName}"))
                    {
                        using (var tr = new StreamReader(filePath))
                        {
                            String htmlText = await tr.ReadToEndAsync();

                            htmlText = htmlText.Replace("$(RootId)", rootId);
                            writer.Write(htmlText);
                            bRendered = true;
                        }
                    }
                }
            }
            if (!bRendered)
            {
                throw new RequestModelException($"The view '{rw.GetView()}' was not found. The following locations were searched:\n{rw.GetRelativePath(".xaml")}\n{rw.GetRelativePath(".html")}");
            }
            writer.Write(modelScript);
        }