Как сгенерировать объекты JSon для запросов ASP.net MVC 4 Ajax?

Когда я обнаружил файлы vsdocs, я подумал о способе использования intellisense в моих файлах JQuery для манипулирования объектами, которые я отправлю на серверную часть моего ASP.net MVC.

Что-то вроде MVC Model, но только для обратных вызовов JQuery Ajax.

Следующий метод JQuery, доступный здесь, используется для передачи пользовательских HTML-тегов по щелчку элемента в объект, предназначенный для передачи обратного вызова ajax: параметры, поступающие из html-объекта, передаются объекту, сохраненному в памяти, при отображении диалогового окна подтверждения.

$.fn.MenuItemConfirmRemove = function (evt) {
    savedEvt = evt;
    RemoveLayoutMenu_JSonModel.DirectURL = $(this).attr("data-DirectURL"),
    RemoveLayoutMenu_JSonModel.LayoutMenu_Translation_Id = $(this).attr("data-id"),
    RemoveLayoutMenu_JSonModel.LayoutMenuTranslationLayoutMenuParent = $(this).attr("data-LayoutMenuTranslationLayoutMenuParent")
    MenuItemAction = RemoveLayoutMenu_JSonModel;
    $.fn.jqDialogConfirm(cap_RemoveMenuItemConfirmTitle, cap_RemoveMenuItemConfirmMessage, cap_RemoveMenuItemConfirmOkButtonTitle, cap_RemoveMenuItemConfirmCancelButtonTitle, "$.fn.MenuItemRemove");
    evt.preventDefault();
}

$.fn.MenuItemRemove - это метод, вызываемый общим диалогом, когда пользователь нажимает кнопку "ОК". Общий диалог доступен здесь

$.fn.MenuItemRemove = function () {
    $('#dialogMessage').dialog('close');
    ajaxData = JSON.stringify(MenuItemAction);
    $.ajax(
    {
        type: "POST",
        url: "/DynaStructure/LayoutMenuItemRemoveItem/" + $("#hidLanguage").val(),
        data: ajaxData,
        contentType: "application/json",
        async: false,
        success: $.fn.MenuUpdated,
        error: function (xhr, ajaxOptions, thrownError) {
            $.fn.jqDialogAlert(DialogErrorTitle, (xhr.responseText));
        }
    });

}

Как вы можете видеть, MenuItemAction заполняется ДО того, как диалог подтверждения загружается и открывается.

MenuItemAction (объявлено глобально) заполняется с помощью RemoveLayoutMenu_JSonModel

Затем в контроллере я должен использовать объект C# для получения этого объекта JQuery следующим образом:

    /// <summary>
    /// Remove a menu
    /// Warning, Removing a Menu remove also its translations
    /// </summary>
    /// <param name="layoutMenu"></param>
    /// <returns></returns>
    [HttpPost, Authorize(Roles = "Admin")]
    public JsonResult LayoutMenuItemRemoveItem(string language, RemoveLayoutMenu_JSonModel ajaxModel)
    {
        JsonResult toReturn = new JsonResult { JsonRequestBehavior = JsonRequestBehavior.AllowGet };
        string eMethod = eMethodBase + "LayoutMenuItemRemoveItem[POST]";
        object eParameters = new { ajaxModel = ajaxModel };
        string defaultLanguage = ConfigurationManager.AppSettings["DefaultLanguage"];
        MembershipUser currentUser = Membership.GetUser();
        LayoutMenu_Translation dbLayoutMenu_Translation;
        using (DataRepositories _dataContext = new DataRepositories())
        {
            Language dbLanguage = _dataContext.Language_Rep.Query(x => x.Description == language).FirstOrDefault();
            if (dbLanguage == null)
            {
                throw new INNOVACALL.Framework.Common.InnovacallExceptions.DataIntegrityException(eMethod, eParameters, string.Format(Resources.ErrMsg_LayoutMenuItemRemove_UnknownLanguage, language));
            }
            using (TransactionScope TS = new TransactionScope())
            {
                try
                {
                    if (ajaxModel.LayoutMenuTranslationLayoutMenuParent == null)
                    {
                        dbLayoutMenu_Translation = _dataContext.LayoutMenu_Translation_Rep.Query(x => x.Id == ajaxModel.LayoutMenu_Translation_Id && x.LayoutMenu.FK_LayoutMenu == null).FirstOrDefault();
                    }
                    else
                    {
                        dbLayoutMenu_Translation = _dataContext.LayoutMenu_Translation_Rep.Query(x => x.Id == ajaxModel.LayoutMenu_Translation_Id && x.LayoutMenu.FK_LayoutMenu == ajaxModel.LayoutMenuTranslationLayoutMenuParent).FirstOrDefault();
                    }
                    if (dbLayoutMenu_Translation == null)
                    {
                        INNOVACALL.Framework.Common.InnovacallExceptions.DataIntegrityException iex = new INNOVACALL.Framework.Common.InnovacallExceptions.DataIntegrityException(eMethod, eParameters, Resources.DynaStructure_MenuAction_MenuNotFound);
                        iex.LogIt();
                        throw iex;
                    }
                    LayoutMenu dbLayoutMenu = dbLayoutMenu_Translation.LayoutMenu;
                    //We check if parent LayoutMenu has child
                    if (dbLayoutMenu_Translation.LayoutMenu.LayoutMenu1.Count > 0)
                    {
                        toReturn.Data = new { @success = false, @divToUpdate = "", @html = "", @scriptToExecute = "$.fn.jqDialogAlert('My Pretty CMS',a.message,'');", @message = Resources.DynaStructure_RemoveMenu_MenuHasChildren };
                    }
                    else
                    {
                        string[] tLanguages = ConfigurationManager.AppSettings["Languages"].Split(',');
                        foreach (string currentLanguage in tLanguages)
                        {
                            Language dbCurrentLanguage = _dataContext.Language_Rep.Query(x => x.Description == currentLanguage).FirstOrDefault();
                            if (dbCurrentLanguage == null) throw new INNOVACALL.Framework.Common.InnovacallExceptions.DataIntegrityException(eMethod, eParameters, Resources.Err_LanguageNotFound);
                            dbLayoutMenu_Translation = dbLayoutMenu.LayoutMenu_Translation.Where(x => x.FK_Language == dbCurrentLanguage.Id).FirstOrDefault();
                            if (dbLayoutMenu_Translation != null)
                            {
                                List<int> Structure_PagesIdsToKill = _dataContext.Structure_Page_Rep.Query(x => x.FK_LayoutMenu_Translation == dbLayoutMenu_Translation.Id).Select(x => x.Id).ToList();
                                foreach (int Structure_PagesIdToKill in Structure_PagesIdsToKill)
                                {
                                    Structure_Page dbStructure_PageToKill = _dataContext.Structure_Page_Rep.GetById(Structure_PagesIdToKill);
                                    ManagedContent toRemove = dbStructure_PageToKill.ManagedContent.SingleOrDefault();
                                    if (toRemove != null)
                                    {
                                        _dataContext.ManagedContent_Rep.Remove(toRemove);
                                        _dataContext.Save();
                                        _dataContext.Structure_Page_Rep.Remove(dbStructure_PageToKill);
                                        _dataContext.Save();
                                    }
                                }
                                _dataContext.LayoutMenu_Translation_Rep.Remove(dbLayoutMenu_Translation);
                                _dataContext.Save();
                            }
                        }
                        string layoutMenuNameToRemove = dbLayoutMenu.Name;
                        _dataContext.LayoutMenu_Rep.Remove(dbLayoutMenu);
                        _dataContext.Save();
                        Logger.Info(enLog.Business, string.Format("User [{0}] removed layout menu [{1}]", (currentUser == null ? "#Anonymous#" : currentUser.UserName), layoutMenuNameToRemove));
                    }
                    TS.Complete();
                }
                catch (INNOVACALL.Framework.Common.InnovacallExceptions.DataIntegrityException iex)
                {
                    TS.Dispose();
                    toReturn.Data = new { @success = false, @scriptToExecute = "$.fn.jqDialogAlert('My Pretty CMS',a.message,'');", @message = iex.Message };
                    return toReturn;
                }
                catch (Exception ex)
                {
                    TS.Dispose();
                    INNOVACALL.Framework.Common.InnovacallExceptions.CommonException iex = new INNOVACALL.Framework.Common.InnovacallExceptions.CommonException(eMethod, eParameters, ex.Message);
                    iex.LogIt();
                    toReturn.Data = new { @success = false, @scriptToExecute = "$.fn.jqDialogAlert('My Pretty CMS',a.message,'');", @message = ex.Message };
                    return toReturn;
                }
            }
            string newMenuBar = RenderMenuBar(_dataContext, dbLanguage, defaultLanguage);
            toReturn.Data = new { @success = true, @divToUpdate = "#divMenuBar", @html = newMenuBar, @scriptToExecute = "$.fn.DocReady();", @message = "" };
        }
        return toReturn;
    }

Источник контроллера ASP.net MVC 4 находится здесь

Повторюсь, вопрос...

Вы пытались сгенерировать объекты JSon на основе класса C# и использовать его, чтобы увидеть intellisense в вашем коде JavaScript при его использовании?

1 ответ

Решение

Я создал этот класс (он, безусловно, может быть улучшен):

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Reflection; 
using System.Web.Script.Serialization;

namespace INNOVACALL.Framework.Common.POCOT4.MVCViewJSObjects {
public class JQClass
{
    private string arg;
    private string sAssemblyName;
    private Assembly assem;
    private Type[] types;

    public Type[] GetTypes()
    {
        return types;
    }

    public JQClass(string sAssemblyName)
    {
        assem = Assembly.LoadFrom(sAssemblyName);
        types = assem.GetTypes();
    }

    public Object CreateInstance(Type type)
    {
        Object myObject = Activator.CreateInstance(type);
        return myObject;
    }

    public List<Type> ObtientListTypesMeta(List<string> ListNom)
    {
        List<Type> listMetaTypes = new List<Type>();
        foreach (string nom in ListNom)
        {
            listMetaTypes.Add(types.ToList().Find(p => p.Name == nom));
        }
        return listMetaTypes;
    }

    public List<string> ObtientListChaineJS(List<string> lstName)
    {
        List<Type> lstTypes = new List<Type>();
        lstTypes = this.ObtientListTypesMeta(lstName);

        List<string> lstObjetJS = new List<string>();
        foreach(Type typeCourant in lstTypes)
        {
            string jqclassMetaData = typeCourant.Name;
            object metaData = this.CreateInstance(typeCourant);

            JavaScriptSerializer serializer = new JavaScriptSerializer();
            serializer.MaxJsonLength = Int32.MaxValue;

            string objetjson = serializer.Serialize(metaData).ToString();

            string chaineJS = "var " + jqclassMetaData + " = " + objetjson;
            lstObjetJS.Add(chaineJS);
        }
        return lstObjetJS;
    }
}
}

Этот класс является своего рода помощником для генерации строк JSon на основе класса C#.

Затем я создал простой POCO T4, как это

<#@ template debug="true" hostSpecific="true" #>
<#@ output extension=".js" #>
<#@ Assembly Name="System.Core.dll" #>
<#@ Assembly Name="System.Windows.Forms.dll" #>
<#@ assembly name="System.Web.Extensions.dll" #>
<#@ Assembly Name="$(SolutionDir)\..\Framework\bin\Debug\INNOVACALL.Framework.Common.dll" #>
<#@ Assembly Name="$(SolutionDir)\..\Portals\MVC4Portal\bin\MyPrettyCMS.dll" #>
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.Web.Script.Serialization" #>
<#@ import namespace="INNOVACALL.Framework.Common.POCOT4.MVCViewJSObjects" #>
<#
List<string> lstName = new List<string>();
string myDll = string.Empty;
myDll = Assembly.GetAssembly(typeof(InnovaApp.Portals.MVC4Portal.Models.JSonModels.LayoutMenuItemFeed_JSonModel)).CodeBase;
lstName.Add( "LayoutMenuItemFeed_JSonModel");
myDll = Assembly.GetAssembly(typeof(InnovaApp.Portals.MVC4Portal.Models.JSonModels.MoveMenuElement_JSonModel)).CodeBase;
lstName.Add( "MoveMenuElement_JSonModel");
myDll = Assembly.GetAssembly(typeof(InnovaApp.Portals.MVC4Portal.Models.JSonModels.RemoveLayoutMenu_JSonModel)).CodeBase;
lstName.Add( "RemoveLayoutMenu_JSonModel");    
myDll = Assembly.GetAssembly(typeof(InnovaApp.Portals.MVC4Portal.Models.JSonModels.ToggleActivation_JSonModel)).CodeBase;
lstName.Add( "ToggleActivation_JSonModel");
JQClass jQClass = new JQClass(myDll);
List<string> lstObjetJS = jQClass.ObtientListChaineJS(lstName);
foreach(string objetJS in lstObjetJS)
{
#>
<#= objetJS #>
<# }
#>

Как видите, я использовал выходное расширение =". Js" для генерации файла js.

это poco сгенерирует этот простой файл (смотрите RemoveLayoutMenu_JSonMode):

var LayoutMenuItemFeed_JSonModel = {"HtmlElementTUpdate":null,"DirectURL":null,"LayoutMenu_Translation_Id":0,"LayoutMenuTranslationLayoutMenuParent":null}
    var MoveMenuElement_JSonModel = {"DirectURL":null,"LayoutMenu_Translation_Id":0,"LayoutMenuTranslationLayoutMenuParent":null,"Direction":0}
    var RemoveLayoutMenu_JSonModel = {"DirectURL":null,"LayoutMenu_Translation_Id":0,"LayoutMenuTranslationLayoutMenuParent":null}
    var ToggleActivation_JSonModel = {"DirectURL":null,"LayoutMenu_Translation_Id":0,"LayoutMenuTranslationLayoutMenuParent":null}

В моем контроллере я указываю _layoutpage для загрузки скрипта, используя мою _controller_base, где T: _model_base

Как это:

        if (this.AdminMode)
        {
            lstSpecificJqueryJSCollection.Add("JSonModels/JSonModelsMenuEdition1.js");
            lstSpecificJqueryJSCollection.Add("InnovacallJS/DynaContent/DynaContentAdmin.js");
            lstSpecificJqueryJSCollection.Add("ClientComponents/tiny_mce/tiny_mce.js");
        }

И ПОЛУЧИТЬ ИНТЕЛЛЕКТУАЛЬНОСТЬ:

Просто ссылайтесь на сгенерированный скрипт, как если бы он был стандартным vsdoc следующим образом:

///<reference path="/Scripts/ClientComponents/jquery/jquery-1.7.2-vsdoc.js" />
///<reference path="/Scripts/InnovacallJS/_Layout/_Layout.js" />
///<reference path="/ScriptsG/inoDynaContentDynamic.js" />
///<reference path="/Scripts/ClientComponents/KendoUI/kendo.web-vsdoc.js" />
///<reference path="/Scripts/JSonModels/JSonModelsMenuEdition1.js" />

Огромное преимущество этого метода заключается в том, что он гарантирует, что все ваши свойства класса C# будут переданы объекту JSon.

Поэтому, если вам нужно добавить свойство, вам просто нужно добавить его в класс C#. Сохраните его и сохраните POCO T4, чтобы восстановить обновленный объект JSon.

Другие вопросы по тегам