Как сгенерировать объекты 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.