Я пробовал внедрение зависимости, но это всегда дает мне HttpContextAccessor.Current
или ActionContext
как ноль, потому что я не в состоянии запроса (я думаю). Итак, как я могу получить этот контекст, чтобы просто взять представление, преобразовать его в строку html (с моделью при необходимости) и выбросить обратно в JS? Я даже пытался напрямую вызвать действие Controller, но оно всегда дает HttpContext как ноль ... Я использую Asp.NET Core 3.
Пожалуйста, если кто-то проходил, помогите мне :-)
Спасибо,
Редактировать:
У меня есть ядро asp.net на базе Electron.net для настольного приложения. Я использую много IPC-коммуникаций для извлечения данных из бэкэнда c #, используя Electron.IpcMain.On
. Я регистрирую действие как слушатель в c # в классе. Основная проблема заключается в том, что этот класс действительно находится за пределами обычного HttpRequest или контроллера. Вот пример кода:
IpcBase Class
public abstract class IpcBase: IBaseIpcCommunicationClass
{
/// <summary>
/// Find a way to get rid of this and take more than the first window
/// </summary>
protected static BrowserWindow _mainWindow = Electron.WindowManager.BrowserWindows.First();
/// <summary>
/// Send an ipcEvent with a parameter class
/// </summary>
/// <param name="parameters">Parameters to fill</param>
public void RegisterIpcEvent<T>(IpcRegisterModel<T> registerModel) => Electron.IpcMain.On(registerModel.key, o => registerModel.action((T)
((JObject)o).ToObject(typeof(T))));
/// <summary>
/// Send a reply inside a registerevent
/// </summary>
/// <typeparam name="T">Type of model</typeparam>
/// <param name="model">model</param>
public void SendReply<T>(IpcSendParamsModel<T> model)
{
if (!string.IsNullOrEmpty(model.replyTo))
{
Electron.IpcMain.Send(_mainWindow, model.replyTo, model);
}
}
...
}
IpcUI (чтобы получить представление контроллера, точно так же, как вызов ajax на контроллере, который получает представление в String (у меня уже есть это, но не с Ipc)
public class IpcUI: IpcBase
{
public IpcUI(IRazorViewToStringService razorViewRenderService)
{
Console.WriteLine("IpcUI::Constructor");
RegisterIpcEvent(new IpcRegisterModel<IpcSendParamsModel<AjaxPartialModel>>("renderPartial", async (param) =>
{
var param = new IpcSendParamsModel<AjaxPartialModel>("RenderPartial")
{
key = "renderPartial",
model = new AjaxPartialModel()
{
DataModel = "{items: [{\r\n MaterialIcon: \"\",\r\n Title: \"Games\",\r\n Selectable: true,\r\n Active: true,\r\n Key: \"GAMES\",\r\n BadgeCaption: \"new\",\r\n BadgeValue: \"123\",\r\n BadgeColor: \"red darken-1\",\r\n BadgePartialLink: \"\",\r\n BadgeContainerLink: \"\",\r\n BadgeModelLink: \"\",\r\n PartialLink: \"Home/Index\",\r\n ContainerLink: \"#body-content\",\r\n ModelLink: \"\"\r\n }] }".JsonDeserialize<MenuModelHeader>(),
PartialName = "PartialViews/_TopMenu"
}
};
try
{
param.results =
await razorViewRenderService.CreateAndResolveInstanceFromGeneric().RenderViewToStringAsync($"~/Views/{param.model.PartialName}.cshtml",
param.model.DataModel);
}
catch (Exception e)
{
IpcClasses.ExceptionManager.SendException(this, e, $"IpcUI params: {param.model.JsonSerialize()}");
}
}));
}
}
Razor Service (в основном взято отсюда Создать строку из вида )
Добавлено при запуске:
services.AddHttpContextAccessor();
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
services.AddScoped<IRazorViewToStringService, RazorRazorViewToStringService>();
Когда я создаю экземпляр IpcUI, DI предоставляет мне услугу, но без какого-либо HttpContext или ActionContext ... Извините за отсутствие информации из моего последнего редактирования :-). Надеюсь, это немного конкретнее.
О! Я что-то забыл, IpcUI создается во время выполнения не с новым (потому что это не работает), но с пользовательской функцией расширения, которая извлекает IServiceProvider для DI:
При запуске
ExtensionsUtils.ServiceProvider = app.ApplicationServices;
В ExtensionsUtils
/// <summary>
/// This is called in configure services to get the collection of services in an extension static class
/// </summary>
public static IServiceProvider ServiceProvider { get; set; }
/// <summary>
/// Create a reference from type T with DI
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="o"></param>
/// <returns></returns>
public static T CreateAndResolveInstanceFromGeneric<T>(this T o)
{
return (T)ActivatorUtilities.CreateInstance<T>(ServiceProvider);
}
Редактировать 2: Я пытался получить доступ к IRazorViewToStringService
из реального конструктора контроллера, и он снова нулевой ... Что я делаю неправильно ???
private readonly IRazorViewToStringService _razorViewRenderService;
public BaseController(IRazorViewToStringService razorViewRenderService)
{
_razorViewRenderService = razorViewRenderService;
}
...
/// <summary>
/// Return a success http code and a View rendered as string
/// </summary>
/// <param name="ViewName">Name of MVC View (or PartialView)</param>
/// <param name="Model">Model to pass if any</param>
/// <returns>JSON: { result: "type", description: "Html Code" }</returns>
public async Task<ActionResult> CheckAndReturnView(string ViewName, object Model = null)
{
return Ok(await _razorViewRenderService.RenderViewToStringAsync(ViewName, Model));
}