如何为ASP.net MVC 4 Ajax请求生成JSon对象?

时间:2022-05-07 06:14:25

When I discovered vsdocs files, I thinked about a way to have intellisense in my JQuery files to manipulate objects I'll send to my ASP.net MVC back end.

当我发现vsdocs文件时,我想到了一种在我的JQuery文件中使用intellisense来操作我将发送到我的ASP.net MVC后端的对象的方法。

Something like MVC Model but just for JQuery Ajax callbacks.

类似于MVC模型,但仅适用于JQuery Ajax回调。

The folowing JQuery method is available here is used to transfert clicked element html custom tags to an object designed to feed an ajax callback : The parameters coming from the html object are transfered to an object keept in memory while confirm dialog is displayed.

这里提供的下面的JQuery方法用于将点击的元素html自定义标签转移到设计用于提供ajax回调的对象:来自html对象的参数在显示确认对话框时被转移到内存中的对象keept。

$.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();
}

the $.fn.MenuItemRemove is the method called by the generic dialog when user click the ok button. The generic dialog is available here

$ .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));
        }
    });

}

As you can see, MenuItemAction is filled BEFORE the confirm dialog is loaded and opened.

如您所见,在加载和打开确认对话框之前,MenuItemAction已填充。

MenuItemAction (declared globally) is filled with RemoveLayoutMenu_JSonModel

MenuItemAction(全局声明)用RemoveLayoutMenu_JSonModel填充

Then, in the controller, I have to use a C# object to receive this JQuery object like that :

然后,在控制器中,我必须使用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;
    }

The source of the ASP.net MVC 4 controller is here

ASP.net MVC 4控制器的源代码在这里

I repeat, the question...

我再说一遍,这个问题......

Did you try to generate JSon objects based on C# class and use it to see intellisense in your javascript code when you use it ?

您是否尝试基于C#类生成JSon对象并在使用它时使用它来查看javascript代码中的intellisense?

1 个解决方案

#1


0  

I created this class (it certainly can be imroved):

我创建了这个类(它当然可以被改造):

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;
    }
}
}

This class is a kind of helper to generate JSon strings based on C# class.

这个类是一种帮助生成基于C#类的JSon字符串。

Then I created a simple POCO T4 like this

然后我创建了一个像这样的简单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 #>
<# }
#>

As you can see, I used output extension=".js" to generate a js file.

如您所见,我使用output extension =“。js”生成一个js文件。

this poco generate this simple file (look the RemoveLayoutMenu_JSonMode) :

这个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}

In my controller, I indicate the _layoutpage to load the script using my _controller_base where T : _model_base

在我的控制器中,我指示_layoutpage使用我的_controller_base加载脚本,其中T:_model_base

Like this :

像这样 :

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

AND TO OBTAIN THE INTELLISENSE :

并获得智力:

Just reference the generated script as if it was a standard vsdoc like this :

只需引用生成的脚本就像它是一个标准的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" />

The HUGE advantage of this technique is that it garantee all your C# class properties will be transfered to the JSon object.

这种技术的巨大优势在于它保证所有C#类属性都将转移到JSon对象。

So if you need to add a property, you just have to add it to the C# class. Save it and Save the POCO T4 to regenerate the updated JSon object.

因此,如果需要添加属性,只需将其添加到C#类即可。保存并保存POCO T4以重新生成更新的JSon对象。

#1


0  

I created this class (it certainly can be imroved):

我创建了这个类(它当然可以被改造):

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;
    }
}
}

This class is a kind of helper to generate JSon strings based on C# class.

这个类是一种帮助生成基于C#类的JSon字符串。

Then I created a simple POCO T4 like this

然后我创建了一个像这样的简单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 #>
<# }
#>

As you can see, I used output extension=".js" to generate a js file.

如您所见,我使用output extension =“。js”生成一个js文件。

this poco generate this simple file (look the RemoveLayoutMenu_JSonMode) :

这个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}

In my controller, I indicate the _layoutpage to load the script using my _controller_base where T : _model_base

在我的控制器中,我指示_layoutpage使用我的_controller_base加载脚本,其中T:_model_base

Like this :

像这样 :

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

AND TO OBTAIN THE INTELLISENSE :

并获得智力:

Just reference the generated script as if it was a standard vsdoc like this :

只需引用生成的脚本就像它是一个标准的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" />

The HUGE advantage of this technique is that it garantee all your C# class properties will be transfered to the JSon object.

这种技术的巨大优势在于它保证所有C#类属性都将转移到JSon对象。

So if you need to add a property, you just have to add it to the C# class. Save it and Save the POCO T4 to regenerate the updated JSon object.

因此,如果需要添加属性,只需将其添加到C#类即可。保存并保存POCO T4以重新生成更新的JSon对象。