add support for 'mvccontroller-crud' and 'apicontroller-crud' (#2929)

* add support for 'mvccontroller-crud' and 'apicontroller-crud'

* logging an error on a missing ValidateEfControllerStep.ControllerType value
This commit is contained in:
Deep Choudhery 2024-08-16 16:13:55 -07:00 коммит произвёл GitHub
Родитель 37e46396bc
Коммит 69409fb574
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
19 изменённых файлов: 1896 добавлений и 25 удалений

Просмотреть файл

@ -0,0 +1,32 @@
{
"Files": [
{
"FileName": "Program.cs",
"Usings": [
"Microsoft.EntityFrameworkCore"
],
"Options": [
"EfScenario"
],
"Methods": {
"Global": {
"CodeChanges": [
{
"InsertAfter": "WebApplication.CreateBuilder",
"CheckBlock": "builder.Configuration.GetConnectionString",
"Block": "\nvar connectionString = builder.Configuration.GetConnectionString(\"$(ConnectionStringName)\") ?? throw new InvalidOperationException(\"Connection string '$(ConnectionStringName)' not found.\")"
},
{
"InsertAfter": "builder.Configuration.GetConnectionString",
"CheckBlock": "builder.Services.AddDbContext",
"Block": "builder.Services.AddDbContext<$(DbContextName)>(options => options.$(UseDbMethod)(connectionString))\"",
"LeadingTrivia": {
"Newline": true
}
}
]
}
}
}
]
}

Просмотреть файл

@ -53,8 +53,8 @@ internal static class BlazorCrudScaffolderBuilderExtensions
PackageConstants.AspNetCorePackages.AspNetCoreDiagnosticsEfCorePackageName
};
if (context.Properties.TryGetValue(nameof(BlazorCrudSettings), out var commandSettingsObj) &&
commandSettingsObj is BlazorCrudSettings commandSettings)
if (context.Properties.TryGetValue(nameof(CrudSettings), out var commandSettingsObj) &&
commandSettingsObj is CrudSettings commandSettings)
{
step.ProjectPath = commandSettings.Project;
step.Prerelease = commandSettings.Prerelease;
@ -81,10 +81,10 @@ internal static class BlazorCrudScaffolderBuilderExtensions
var step = config.Step;
var codeModificationFilePath = GlobalToolFileFinder.FindCodeModificationConfigFile("blazorWebCrudChanges.json", System.Reflection.Assembly.GetExecutingAssembly());
//get needed properties and cast them as needed
config.Context.Properties.TryGetValue(nameof(BlazorCrudSettings), out var blazorCrudSettingsObj);
config.Context.Properties.TryGetValue(nameof(CrudSettings), out var blazorCrudSettingsObj);
config.Context.Properties.TryGetValue(nameof(BlazorCrudModel), out var blazorCrudModelObj);
config.Context.Properties.TryGetValue(Constants.StepConstants.CodeModifierProperties, out var codeModifierPropertiesObj);
var blazorCrudSettings = blazorCrudSettingsObj as BlazorCrudSettings;
var blazorCrudSettings = blazorCrudSettingsObj as CrudSettings;
var codeModifierProperties = codeModifierPropertiesObj as Dictionary<string, string>;
var blazorCrudModel = blazorCrudModelObj as BlazorCrudModel;
@ -115,10 +115,10 @@ internal static class BlazorCrudScaffolderBuilderExtensions
builder = builder.WithStep<CodeModificationStep>(config =>
{
var step = config.Step;
config.Context.Properties.TryGetValue(nameof(BlazorCrudSettings), out var blazorCrudSettingsObj);
config.Context.Properties.TryGetValue(nameof(CrudSettings), out var blazorCrudSettingsObj);
config.Context.Properties.TryGetValue(Constants.StepConstants.AdditionalCodeModifier, out var blazorCodeModifierStringObj);
config.Context.Properties.TryGetValue(nameof(BlazorCrudModel), out var blazorCrudModelObj);
var blazorCrudSettings = blazorCrudSettingsObj as BlazorCrudSettings;
var blazorCrudSettings = blazorCrudSettingsObj as CrudSettings;
var blazorCrudModel = blazorCrudModelObj as BlazorCrudModel;
var blazorCodeModifierString = blazorCodeModifierStringObj as string;
if (blazorCrudSettings is not null &&

Просмотреть файл

@ -0,0 +1,111 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.DotNet.Scaffolding.CodeModification;
using Microsoft.DotNet.Scaffolding.Core.Builder;
using Microsoft.DotNet.Scaffolding.Core.Steps;
using Microsoft.DotNet.Scaffolding.Internal;
using Microsoft.DotNet.Scaffolding.TextTemplating;
using Microsoft.DotNet.Tools.Scaffold.AspNet.Common;
using Microsoft.DotNet.Tools.Scaffold.AspNet.Helpers;
using Microsoft.DotNet.Tools.Scaffold.AspNet.Models;
using Microsoft.DotNet.Tools.Scaffold.AspNet.ScaffoldSteps.Settings;
namespace Microsoft.DotNet.Scaffolding.Core.Hosting;
internal static class EfControllerScaffolderBuilderExtensions
{
public static IScaffoldBuilder WithEfControllerTextTemplatingStep(this IScaffoldBuilder builder)
{
return builder.WithStep<TextTemplatingStep>(config =>
{
var step = config.Step;
var context = config.Context;
context.Properties.TryGetValue(nameof(EfControllerModel), out var efControllerModelObj);
EfControllerModel efControllerModel = efControllerModelObj as EfControllerModel ??
throw new InvalidOperationException("missing 'EfControllerModel' in 'ScaffolderContext.Properties'");
var efControllerTemplateProperty = EfControllerHelper.GetEfControllerTemplatingProperty(efControllerModel);
if (efControllerTemplateProperty is not null)
{
step.TextTemplatingProperties = [efControllerTemplateProperty];
step.DisplayName = $"{efControllerModel.ControllerType} controller";
}
else
{
step.SkipStep = true;
return;
}
});
}
public static IScaffoldBuilder WithEfControllerAddPackagesStep(this IScaffoldBuilder builder)
{
return builder.WithStep<AddPackagesStep>(config =>
{
var step = config.Step;
var context = config.Context;
var packageList = new List<string>()
{
PackageConstants.EfConstants.EfToolsPackageName
};
if (context.Properties.TryGetValue(nameof(EfControllerSettings), out var commandSettingsObj) &&
commandSettingsObj is EfControllerSettings commandSettings)
{
step.ProjectPath = commandSettings.Project;
step.Prerelease = commandSettings.Prerelease;
if (!string.IsNullOrEmpty(commandSettings.DatabaseProvider) &&
PackageConstants.EfConstants.EfPackagesDict.TryGetValue(commandSettings.DatabaseProvider, out string? projectPackageName))
{
packageList.Add(projectPackageName);
}
step.PackageNames = packageList;
}
else
{
step.SkipStep = true;
return;
}
});
}
public static IScaffoldBuilder WithEfControllerCodeChangeStep(this IScaffoldBuilder builder)
{
builder = builder.WithStep<CodeModificationStep>(config =>
{
var step = config.Step;
var codeModificationFilePath = GlobalToolFileFinder.FindCodeModificationConfigFile("efControllerChanges.json", System.Reflection.Assembly.GetExecutingAssembly());
//get needed properties and cast them as needed
config.Context.Properties.TryGetValue(nameof(EfControllerSettings), out var efControllerSettingsObj);
config.Context.Properties.TryGetValue(nameof(EfControllerModel), out var efControllerModelObj);
config.Context.Properties.TryGetValue(Internal.Constants.StepConstants.CodeModifierProperties, out var codeModifierPropertiesObj);
var efControllerSettings = efControllerSettingsObj as EfControllerSettings;
var codeModifierProperties = codeModifierPropertiesObj as Dictionary<string, string>;
var efControllerModel = efControllerModelObj as EfControllerModel;
//initialize CodeModificationStep's properties
if (!string.IsNullOrEmpty(codeModificationFilePath) &&
efControllerSettings is not null &&
codeModifierProperties is not null &&
efControllerModel is not null)
{
step.CodeModifierConfigPath = codeModificationFilePath;
foreach (var kvp in codeModifierProperties)
{
step.CodeModifierProperties.TryAdd(kvp.Key, kvp.Value);
}
step.ProjectPath = efControllerSettings.Project;
step.CodeChangeOptions = efControllerModel.ProjectInfo.CodeChangeOptions ?? [];
}
else
{
step.SkipStep = true;
return;
}
});
return builder;
}
}

Просмотреть файл

@ -0,0 +1,60 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.DotNet.Scaffolding.TextTemplating;
using Microsoft.DotNet.Tools.Scaffold.AspNet.Models;
namespace Microsoft.DotNet.Tools.Scaffold.AspNet.Helpers;
internal static class EfControllerHelper
{
internal static TextTemplatingProperty GetEfControllerTemplatingProperty(EfControllerModel efControllerModel)
{
var allT4Templates = new TemplateFoldersUtilities().GetAllT4Templates(["EfController"]);
string? t4TemplatePath = null;
if (efControllerModel.ControllerType.Equals("API", StringComparison.OrdinalIgnoreCase))
{
t4TemplatePath = allT4Templates.FirstOrDefault(x => x.EndsWith("ApiEfController.tt", StringComparison.OrdinalIgnoreCase));
}
else
{
t4TemplatePath = allT4Templates.FirstOrDefault(x => x.EndsWith("MvcEfController.tt", StringComparison.OrdinalIgnoreCase));
}
var templateType = GetCrudControllerType(t4TemplatePath);
if (string.IsNullOrEmpty(t4TemplatePath) ||
templateType is null)
{
throw new InvalidOperationException($"Could not find '{efControllerModel.ControllerType}' template");
}
return new TextTemplatingProperty
{
TemplatePath = t4TemplatePath,
TemplateType = templateType,
TemplateModel = efControllerModel,
TemplateModelName = "Model",
OutputPath = Path.Combine(efControllerModel.ControllerOutputPath, $"{efControllerModel.ControllerName}.cs")
};
}
private static Type? GetCrudControllerType(string? templatePath)
{
if (string.IsNullOrEmpty(templatePath))
{
return null;
}
switch (Path.GetFileName(templatePath))
{
case "ApiEfController.tt":
return typeof(Templates.EfController.ApiEfController);
case "MvcEfController.tt":
return typeof(Templates.EfController.MvcEfController);
default:
break;
}
return null;
}
}

Просмотреть файл

@ -1,16 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.DotNet.Tools.Scaffold.AspNet.Common;
namespace Microsoft.DotNet.Tools.Scaffold.AspNet.Models;
internal class BlazorCrudModel
internal class BlazorCrudModel : CrudModel
{
public required string PageType { get; init; }
public required DbContextInfo DbContextInfo { get; init; }
public required ModelInfo ModelInfo { get; init; }
public required ProjectInfo ProjectInfo { get; init; }
//used to get correct Input tag to add to BlazorCrud\Create.tt and BlazorCrud\Edit.tt template
public string GetInputType(string inputType)
{

Просмотреть файл

@ -0,0 +1,13 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.DotNet.Tools.Scaffold.AspNet.Common;
namespace Microsoft.DotNet.Tools.Scaffold.AspNet.Models;
internal class CrudModel
{
public required string PageType { get; init; }
public required DbContextInfo DbContextInfo { get; init; }
public required ModelInfo ModelInfo { get; init; }
public required ProjectInfo ProjectInfo { get; init; }
}

Просмотреть файл

@ -0,0 +1,15 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.DotNet.Tools.Scaffold.AspNet.Common;
namespace Microsoft.DotNet.Tools.Scaffold.AspNet.Models;
internal class EfControllerModel
{
public required string ControllerType { get; set; }
public required string ControllerName { get; set; }
public required string ControllerOutputPath { get; set; }
public required DbContextInfo DbContextInfo { get; init; }
public required ModelInfo ModelInfo { get; init; }
public required ProjectInfo ProjectInfo { get; init; }
}

Просмотреть файл

@ -21,7 +21,7 @@ public static class Program
out var projectOption, out var prereleaseOption, out var fileNameOption, out var actionsOption,
out var areaNameOption, out var modelNameOption, out var endpointsClassOption, out var databaseProviderOption,
out var databaseProviderRequiredOption, out var dataContextClassOption, out var dataContextClassRequiredOption,
out var openApiOption, out var pageTypeOption);
out var openApiOption, out var pageTypeOption, out var controllerNameOption);
builder.AddScaffolder("blazor-empty")
.WithDisplayName("Razor Component - Empty")
@ -98,8 +98,54 @@ public static class Program
step.CommandName = "mvccontroller";
});
builder.AddScaffolder("apicontroller-crud")
.WithDisplayName("API Controller with actions, using Entity Framework (CRUD)")
.WithCategory("API")
.WithDescription("Create an API controller with REST actions to create, read, update, delete, and list entities")
.WithOptions([projectOption, modelNameOption, controllerNameOption, dataContextClassRequiredOption, databaseProviderRequiredOption, prereleaseOption])
.WithStep<ValidateEfControllerStep>(config =>
{
var step = config.Step;
var context = config.Context;
step.Project = context.GetOptionResult(projectOption);
step.Model = context.GetOptionResult(modelNameOption);
step.DataContext = context.GetOptionResult(dataContextClassRequiredOption);
step.DatabaseProvider = context.GetOptionResult(databaseProviderRequiredOption);
step.Prerelease = context.GetOptionResult(prereleaseOption);
step.ControllerType = "API";
step.ControllerName = context.GetOptionResult(controllerNameOption);
})
.WithEfControllerAddPackagesStep()
.WithDbContextStep()
.WithConnectionStringStep()
.WithEfControllerTextTemplatingStep()
.WithEfControllerCodeChangeStep();
builder.AddScaffolder("mvccontroller-crud")
.WithDisplayName("MVC Controller with views, using Entity Framework (CRUD)")
.WithCategory("MVC")
.WithDescription("Create a MVC controller with read/write actions and views using Entity Framework")
.WithOptions([projectOption, modelNameOption, controllerNameOption, dataContextClassRequiredOption, databaseProviderRequiredOption])
.WithStep<ValidateEfControllerStep>(config =>
{
var step = config.Step;
var context = config.Context;
step.Project = context.GetOptionResult(projectOption);
step.Model = context.GetOptionResult(modelNameOption);
step.DataContext = context.GetOptionResult(dataContextClassRequiredOption);
step.DatabaseProvider = context.GetOptionResult(databaseProviderRequiredOption);
step.Prerelease = context.GetOptionResult(prereleaseOption);
step.ControllerType = "MVC";
step.ControllerName = context.GetOptionResult(controllerNameOption);
})
.WithEfControllerAddPackagesStep()
.WithDbContextStep()
.WithConnectionStringStep()
.WithEfControllerTextTemplatingStep()
.WithEfControllerCodeChangeStep();
builder.AddScaffolder("blazor-crud")
.WithDisplayName("Razor Components w/ EF (CRUD)")
.WithDisplayName("Razor Components with EntityFrameworkCore (CRUD)")
.WithCategory("Blazor")
.WithDescription("Generates Razor Components using Entity Framework for Create, Delete, Details, Edit and List operations for the given model")
.WithOptions([projectOption, modelNameOption, dataContextClassRequiredOption, databaseProviderRequiredOption, pageTypeOption, prereleaseOption])
@ -177,6 +223,7 @@ public static class Program
services.AddTransient<AreaScaffolderStep>();
services.AddTransient<DotnetNewScaffolderStep>();
services.AddTransient<EmptyControllerScaffolderStep>();
services.AddTransient<ValidateEfControllerStep>();
}
static void CreateOptions(
@ -192,7 +239,8 @@ public static class Program
out ScaffolderOption<string> dataContextClassOption,
out ScaffolderOption<string> dataContextClassRequiredOption,
out ScaffolderOption<bool> openApiOption,
out ScaffolderOption<string> pageTypeOption)
out ScaffolderOption<string> pageTypeOption,
out ScaffolderOption<string> controllerNameOption)
{
projectOption = new ScaffolderOption<string>
{
@ -229,6 +277,14 @@ public static class Program
PickerType = InteractivePickerType.YesNo
};
controllerNameOption = new ScaffolderOption<string>
{
DisplayName = "Controller Name",
CliOption = "--controller",
Description = "Name for the controller being created",
Required = true
};
areaNameOption = new ScaffolderOption<string>
{
DisplayName = "Area Name",

Просмотреть файл

@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
namespace Microsoft.DotNet.Tools.Scaffold.AspNet.ScaffoldSteps.Settings;
internal class BlazorCrudSettings : EfWithModelStepSettings
internal class CrudSettings : EfWithModelStepSettings
{
public required string Page { get; set; }
}

Просмотреть файл

@ -0,0 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
namespace Microsoft.DotNet.Tools.Scaffold.AspNet.ScaffoldSteps.Settings;
internal class EfControllerSettings : EfWithModelStepSettings
{
public required string ControllerType { get; set; }
public required string ControllerName { get; set; }
}

Просмотреть файл

@ -27,7 +27,7 @@ internal class ValidateBlazorCrudStep : ScaffoldStep
public ValidateBlazorCrudStep(
IFileSystem fileSystem,
ILogger<ValidateMinimalApiStep> logger)
ILogger<ValidateBlazorCrudStep> logger)
{
_fileSystem = fileSystem;
_logger = logger;
@ -43,7 +43,7 @@ internal class ValidateBlazorCrudStep : ScaffoldStep
}
else
{
context.Properties.Add(nameof(BlazorCrudSettings), blazorCrudSettings);
context.Properties.Add(nameof(CrudSettings), blazorCrudSettings);
}
//initialize MinimalApiModel
@ -89,7 +89,7 @@ internal class ValidateBlazorCrudStep : ScaffoldStep
return true;
}
private BlazorCrudSettings? ValidateBlazorCrudSettings()
private CrudSettings? ValidateBlazorCrudSettings()
{
if (string.IsNullOrEmpty(Project) || !_fileSystem.FileExists(Project))
{
@ -124,7 +124,7 @@ internal class ValidateBlazorCrudStep : ScaffoldStep
DatabaseProvider = PackageConstants.EfConstants.SqlServer;
}
return new BlazorCrudSettings
return new CrudSettings
{
Model = Model,
Project = Project,
@ -135,7 +135,7 @@ internal class ValidateBlazorCrudStep : ScaffoldStep
};
}
private async Task<BlazorCrudModel?> GetBlazorCrudModelAsync(BlazorCrudSettings settings)
private async Task<BlazorCrudModel?> GetBlazorCrudModelAsync(CrudSettings settings)
{
var projectInfo = ClassAnalyzers.GetProjectInfo(settings.Project, _logger);
if (projectInfo is null || projectInfo.CodeService is null)

Просмотреть файл

@ -0,0 +1,205 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.DotNet.Scaffolding.Core.Scaffolders;
using Microsoft.DotNet.Scaffolding.Core.Steps;
using Microsoft.DotNet.Scaffolding.Internal.Services;
using Microsoft.DotNet.Scaffolding.TextTemplating.DbContext;
using Microsoft.DotNet.Tools.Scaffold.AspNet.Common;
using Microsoft.DotNet.Tools.Scaffold.AspNet.Helpers;
using Microsoft.DotNet.Tools.Scaffold.AspNet.Models;
using Microsoft.DotNet.Tools.Scaffold.AspNet.ScaffoldSteps.Settings;
using Microsoft.Extensions.Logging;
using Constants = Microsoft.DotNet.Scaffolding.Internal.Constants;
namespace Microsoft.DotNet.Tools.Scaffold.AspNet.ScaffoldSteps;
internal class ValidateEfControllerStep : ScaffoldStep
{
private readonly IFileSystem _fileSystem;
private readonly ILogger _logger;
public string? Project { get; set; }
public bool Prerelease { get; set; }
public string? DatabaseProvider { get; set; }
public string? DataContext { get; set; }
public string? Model { get; set; }
public string? ControllerName { get; set; }
public string? ControllerType { get; set; }
public ValidateEfControllerStep(
IFileSystem fileSystem,
ILogger<ValidateEfControllerStep> logger)
{
_fileSystem = fileSystem;
_logger = logger;
}
public override async Task<bool> ExecuteAsync(ScaffolderContext context, CancellationToken cancellationToken = default)
{
var efControllerSettings = ValidateEfControllerSettings();
var codeModifierProperties = new Dictionary<string, string>();
if (efControllerSettings is null)
{
return false;
}
else
{
context.Properties.Add(nameof(EfControllerSettings), efControllerSettings);
}
//initialize CrudControllerModel
_logger.LogInformation("Initializing scaffolding model...");
var efControllerModel = await GetEfControllerModelAsync(efControllerSettings);
if (efControllerModel is null)
{
_logger.LogError("An error occurred.");
return false;
}
else
{
context.Properties.Add(nameof(EfControllerModel), efControllerModel);
}
//Install packages and add a DbContext (if needed)
if (efControllerModel.DbContextInfo.EfScenario)
{
var dbContextProperties = AspNetDbContextHelper.GetDbContextProperties(efControllerSettings.Project, efControllerModel.DbContextInfo);
if (dbContextProperties is not null)
{
context.Properties.Add(nameof(DbContextProperties), dbContextProperties);
}
var projectBasePath = Path.GetDirectoryName(efControllerSettings.Project);
if (!string.IsNullOrEmpty(projectBasePath))
{
context.Properties.Add(Constants.StepConstants.BaseProjectPath, projectBasePath);
}
codeModifierProperties = AspNetDbContextHelper.GetDbContextCodeModifierProperties(efControllerModel.DbContextInfo);
}
context.Properties.Add(Constants.StepConstants.CodeModifierProperties, codeModifierProperties);
return true;
}
private EfControllerSettings? ValidateEfControllerSettings()
{
if (string.IsNullOrEmpty(Project) || !_fileSystem.FileExists(Project))
{
_logger.LogError("Missing/Invalid --project option.");
return null;
}
if (string.IsNullOrEmpty(Model))
{
_logger.LogError("Missing/Invalid --model option.");
return null;
}
if (string.IsNullOrEmpty(ControllerName))
{
_logger.LogError("Missing/Invalid --controller option.");
return null;
}
else
{
ControllerName = Path.GetFileNameWithoutExtension(ControllerName);
}
if (string.IsNullOrEmpty(ControllerType))
{
_logger.LogError($"Missing/Invalid '{nameof(ValidateEfControllerStep.ControllerType)}' value.");
return null;
}
else if (
!string.IsNullOrEmpty(ControllerType) &&
!ControllerType.Equals("API", StringComparison.OrdinalIgnoreCase) &&
!ControllerType.Equals("MVC", StringComparison.OrdinalIgnoreCase))
{
//defaulting to API controller
ControllerType = "API";
}
if (string.IsNullOrEmpty(DataContext))
{
_logger.LogError("Missing/Invalid --dataContext option.");
return null;
}
else if (string.IsNullOrEmpty(DatabaseProvider) || !PackageConstants.EfConstants.EfPackagesDict.ContainsKey(DatabaseProvider))
{
DatabaseProvider = PackageConstants.EfConstants.SqlServer;
}
return new EfControllerSettings
{
Model = Model,
ControllerName = ControllerName,
Project = Project,
ControllerType = ControllerType,
DataContext = DataContext,
DatabaseProvider = DatabaseProvider,
Prerelease = Prerelease
};
}
private async Task<EfControllerModel?> GetEfControllerModelAsync(EfControllerSettings settings)
{
var projectInfo = ClassAnalyzers.GetProjectInfo(settings.Project, _logger);
var projectDirectory = Path.GetDirectoryName(projectInfo.ProjectPath);
if (projectInfo is null || projectInfo.CodeService is null || string.IsNullOrEmpty(projectDirectory))
{
return null;
}
//find and set --model class properties
ModelInfo? modelInfo = null;
var allClasses = await projectInfo.CodeService.GetAllClassSymbolsAsync();
var modelClassSymbol = allClasses.FirstOrDefault(x => x.Name.Equals(settings.Model, StringComparison.OrdinalIgnoreCase));
if (string.IsNullOrEmpty(settings.Model) || modelClassSymbol is null)
{
_logger.LogError($"Invalid --model '{settings.Model}'");
return null;
}
else
{
modelInfo = ClassAnalyzers.GetModelClassInfo(modelClassSymbol);
}
var validateModelInfoResult = ClassAnalyzers.ValidateModelForCrudScaffolders(modelInfo, _logger);
if (!validateModelInfoResult)
{
_logger.LogError($"Invalid --model '{settings.Model}'");
return null;
}
//find DbContext info or create properties for a new one.
var dbContextClassName = settings.DataContext;
DbContextInfo dbContextInfo = new();
if (!string.IsNullOrEmpty(dbContextClassName) && !string.IsNullOrEmpty(settings.DatabaseProvider))
{
var dbContextClassSymbol = allClasses.FirstOrDefault(x => x.Name.Equals(dbContextClassName, StringComparison.OrdinalIgnoreCase));
dbContextInfo = ClassAnalyzers.GetDbContextInfo(settings.Project, dbContextClassSymbol, dbContextClassName, settings.DatabaseProvider, settings.Model);
dbContextInfo.EfScenario = true;
}
EfControllerModel scaffoldingModel = new()
{
ControllerName = settings.ControllerName,
ControllerType = settings.ControllerType,
ProjectInfo = projectInfo,
ModelInfo = modelInfo,
DbContextInfo = dbContextInfo,
ControllerOutputPath = projectDirectory
};
if (scaffoldingModel.ProjectInfo is not null && scaffoldingModel.ProjectInfo.CodeService is not null)
{
scaffoldingModel.ProjectInfo.CodeChangeOptions =
[
scaffoldingModel.DbContextInfo.EfScenario ? "EfScenario" : string.Empty
];
}
return scaffoldingModel;
}
}

Просмотреть файл

@ -0,0 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.DotNet.Scaffolding.TextTemplating;
namespace Microsoft.DotNet.Tools.Scaffold.AspNet.Templates.EfController;
public partial class ApiEfController : ITextTransformation
{
}

Просмотреть файл

@ -0,0 +1,503 @@
// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version: 17.0.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
// ------------------------------------------------------------------------------
namespace Microsoft.DotNet.Tools.Scaffold.AspNet.Templates.EfController
{
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System;
/// <summary>
/// Class to produce the template output
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
public partial class ApiEfController : ApiEfControllerBase
{
/// <summary>
/// Create the template output
/// </summary>
public virtual string TransformText()
{
string modelName = Model.ModelInfo.ModelTypeName;
string modelNameUpperVariant = modelName.ToUpperInvariant();
string modelNameLowerVariant = modelName.ToLowerInvariant();
string pluralModel = Model.ModelInfo.ModelTypePluralName.ToUpperInvariant();
string dbContextNamespace = string.IsNullOrEmpty(Model.DbContextInfo.DbContextNamespace) ? string.Empty : Model.DbContextInfo.DbContextNamespace;
string dbContextName = Model.DbContextInfo.DbContextClassName;
string entitySetName = Model.DbContextInfo.EntitySetVariableName ?? modelName;
string modelNamespace = Model.ModelInfo.ModelNamespace;
this.Write("using Microsoft.AspNetCore.Mvc;\r\nusing Microsoft.EntityFrameworkCore;\r\n");
if (!string.IsNullOrEmpty(modelNamespace))
{
this.Write("using ");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNamespace));
this.Write(";\r\n");
}
if (!string.IsNullOrEmpty(dbContextNamespace))
{
this.Write("using ");
this.Write(this.ToStringHelper.ToStringWithCulture(dbContextNamespace));
this.Write(";\r\n");
}
this.Write("\r\n[Route(\"api/[controller]\")]\r\n[ApiController]\r\npublic class ");
this.Write(this.ToStringHelper.ToStringWithCulture(Model.ControllerName));
this.Write(" : ControllerBase\r\n{\r\n private readonly ");
this.Write(this.ToStringHelper.ToStringWithCulture(dbContextName));
this.Write(" _context;\r\n\r\n public ");
this.Write(this.ToStringHelper.ToStringWithCulture(Model.ControllerName));
this.Write("(");
this.Write(this.ToStringHelper.ToStringWithCulture(dbContextName));
this.Write(" context)\r\n {\r\n _context = context;\r\n }\r\n\r\n // GET: api/");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write("\r\n [HttpGet]\r\n public async Task<ActionResult<IEnumerable<");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write(">>> Get");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write("()\r\n {\r\n return await _context.");
this.Write(this.ToStringHelper.ToStringWithCulture(entitySetName));
this.Write(".ToListAsync();\r\n }\r\n\r\n // GET: api/");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write("/5\r\n [HttpGet(\"{id}\")]\r\n public async Task<ActionResult<");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write(">> Get");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write("(int id)\r\n {\r\n var ");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerVariant));
this.Write(" = await _context.");
this.Write(this.ToStringHelper.ToStringWithCulture(entitySetName));
this.Write(".FindAsync(id);\r\n\r\n if (");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerVariant));
this.Write(" == null)\r\n {\r\n return NotFound();\r\n }\r\n\r\n return" +
" ");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerVariant));
this.Write(";\r\n }\r\n\r\n // PUT: api/");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write("/5\r\n // To protect from overposting attacks, see https://go.microsoft.com/fwli" +
"nk/?linkid=2123754\r\n [HttpPut(\"{id}\")]\r\n public async Task<IActionResult> " +
"Put");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write("(int id, ");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerVariant));
this.Write(")\r\n {\r\n if (id != ");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerVariant));
this.Write(".ID)\r\n {\r\n return BadRequest();\r\n }\r\n\r\n _context." +
"Entry(");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerVariant));
this.Write(").State = EntityState.Modified;\r\n\r\n try\r\n {\r\n await _con" +
"text.SaveChangesAsync();\r\n }\r\n catch (DbUpdateConcurrencyException" +
")\r\n {\r\n if (!");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write("Exists(id))\r\n {\r\n return NotFound();\r\n }\r\n " +
" else\r\n {\r\n throw;\r\n }\r\n }\r" +
"\n\r\n return NoContent();\r\n }\r\n\r\n // POST: api/");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write("\r\n // To protect from overposting attacks, see https://go.microsoft.com/fwlink" +
"/?linkid=2123754\r\n [HttpPost]\r\n public async Task<ActionResult<");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write(">> Post");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write("(");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write(" ");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerVariant));
this.Write(")\r\n {\r\n _context.");
this.Write(this.ToStringHelper.ToStringWithCulture(entitySetName));
this.Write(".Add(");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerVariant));
this.Write(");\r\n await _context.SaveChangesAsync();\r\n\r\n return CreatedAtAction(" +
"\"Get");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write("\", new { id = ");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerVariant));
this.Write(".ID }, ");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerVariant));
this.Write(");\r\n }\r\n\r\n // DELETE: api/");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write("/5\r\n [HttpDelete(\"{id}\")]\r\n public async Task<IActionResult> Delete");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write("(int id)\r\n {\r\n var ");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerVariant));
this.Write(" = await _context.");
this.Write(this.ToStringHelper.ToStringWithCulture(entitySetName));
this.Write(".FindAsync(id);\r\n if (");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerVariant));
this.Write(" == null)\r\n {\r\n return NotFound();\r\n }\r\n\r\n _conte" +
"xt.");
this.Write(this.ToStringHelper.ToStringWithCulture(entitySetName));
this.Write(".Remove(");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerVariant));
this.Write(");\r\n await _context.SaveChangesAsync();\r\n\r\n return NoContent();\r\n " +
" }\r\n\r\n private bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write("Exists(int id)\r\n {\r\n return _context.");
this.Write(this.ToStringHelper.ToStringWithCulture(entitySetName));
this.Write(".Any(e => e.ID == id);\r\n }\r\n}\r\n");
return this.GenerationEnvironment.ToString();
}
private global::Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost hostValue;
/// <summary>
/// The current host for the text templating engine
/// </summary>
public virtual global::Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost Host
{
get
{
return this.hostValue;
}
set
{
this.hostValue = value;
}
}
private global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.EfControllerModel _ModelField;
/// <summary>
/// Access the Model parameter of the template.
/// </summary>
private global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.EfControllerModel Model
{
get
{
return this._ModelField;
}
}
/// <summary>
/// Initialize the template
/// </summary>
public virtual void Initialize()
{
if ((this.Errors.HasErrors == false))
{
bool ModelValueAcquired = false;
if (this.Session.ContainsKey("Model"))
{
this._ModelField = ((global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.EfControllerModel)(this.Session["Model"]));
ModelValueAcquired = true;
}
if ((ModelValueAcquired == false))
{
string parameterValue = this.Host.ResolveParameterValue("Property", "PropertyDirectiveProcessor", "Model");
if ((string.IsNullOrEmpty(parameterValue) == false))
{
global::System.ComponentModel.TypeConverter tc = global::System.ComponentModel.TypeDescriptor.GetConverter(typeof(global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.EfControllerModel));
if (((tc != null)
&& tc.CanConvertFrom(typeof(string))))
{
this._ModelField = ((global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.EfControllerModel)(tc.ConvertFrom(parameterValue)));
ModelValueAcquired = true;
}
else
{
this.Error("The type \'Microsoft.DotNet.Tools.Scaffold.AspNet.Models.EfControllerModel\' of the" +
" parameter \'Model\' did not match the type of the data passed to the template.");
}
}
}
if ((ModelValueAcquired == false))
{
object data = global::Microsoft.DotNet.Scaffolding.TextTemplating.CallContext.LogicalGetData("Model");
if ((data != null))
{
this._ModelField = ((global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.EfControllerModel)(data));
}
}
}
}
}
#region Base class
/// <summary>
/// Base class for this transformation
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
public class ApiEfControllerBase
{
#region Fields
private global::System.Text.StringBuilder generationEnvironmentField;
private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField;
private global::System.Collections.Generic.List<int> indentLengthsField;
private string currentIndentField = "";
private bool endsWithNewline;
private global::System.Collections.Generic.IDictionary<string, object> sessionField;
#endregion
#region Properties
/// <summary>
/// The string builder that generation-time code is using to assemble generated output
/// </summary>
public System.Text.StringBuilder GenerationEnvironment
{
get
{
if ((this.generationEnvironmentField == null))
{
this.generationEnvironmentField = new global::System.Text.StringBuilder();
}
return this.generationEnvironmentField;
}
set
{
this.generationEnvironmentField = value;
}
}
/// <summary>
/// The error collection for the generation process
/// </summary>
public System.CodeDom.Compiler.CompilerErrorCollection Errors
{
get
{
if ((this.errorsField == null))
{
this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection();
}
return this.errorsField;
}
}
/// <summary>
/// A list of the lengths of each indent that was added with PushIndent
/// </summary>
private System.Collections.Generic.List<int> indentLengths
{
get
{
if ((this.indentLengthsField == null))
{
this.indentLengthsField = new global::System.Collections.Generic.List<int>();
}
return this.indentLengthsField;
}
}
/// <summary>
/// Gets the current indent we use when adding lines to the output
/// </summary>
public string CurrentIndent
{
get
{
return this.currentIndentField;
}
}
/// <summary>
/// Current transformation session
/// </summary>
public virtual global::System.Collections.Generic.IDictionary<string, object> Session
{
get
{
return this.sessionField;
}
set
{
this.sessionField = value;
}
}
#endregion
#region Transform-time helpers
/// <summary>
/// Write text directly into the generated output
/// </summary>
public void Write(string textToAppend)
{
if (string.IsNullOrEmpty(textToAppend))
{
return;
}
// If we're starting off, or if the previous text ended with a newline,
// we have to append the current indent first.
if (((this.GenerationEnvironment.Length == 0)
|| this.endsWithNewline))
{
this.GenerationEnvironment.Append(this.currentIndentField);
this.endsWithNewline = false;
}
// Check if the current text ends with a newline
if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture))
{
this.endsWithNewline = true;
}
// This is an optimization. If the current indent is "", then we don't have to do any
// of the more complex stuff further down.
if ((this.currentIndentField.Length == 0))
{
this.GenerationEnvironment.Append(textToAppend);
return;
}
// Everywhere there is a newline in the text, add an indent after it
textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField));
// If the text ends with a newline, then we should strip off the indent added at the very end
// because the appropriate indent will be added when the next time Write() is called
if (this.endsWithNewline)
{
this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length));
}
else
{
this.GenerationEnvironment.Append(textToAppend);
}
}
/// <summary>
/// Write text directly into the generated output
/// </summary>
public void WriteLine(string textToAppend)
{
this.Write(textToAppend);
this.GenerationEnvironment.AppendLine();
this.endsWithNewline = true;
}
/// <summary>
/// Write formatted text directly into the generated output
/// </summary>
public void Write(string format, params object[] args)
{
this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
}
/// <summary>
/// Write formatted text directly into the generated output
/// </summary>
public void WriteLine(string format, params object[] args)
{
this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
}
/// <summary>
/// Raise an error
/// </summary>
public void Error(string message)
{
System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
error.ErrorText = message;
this.Errors.Add(error);
}
/// <summary>
/// Raise a warning
/// </summary>
public void Warning(string message)
{
System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
error.ErrorText = message;
error.IsWarning = true;
this.Errors.Add(error);
}
/// <summary>
/// Increase the indent
/// </summary>
public void PushIndent(string indent)
{
if ((indent == null))
{
throw new global::System.ArgumentNullException("indent");
}
this.currentIndentField = (this.currentIndentField + indent);
this.indentLengths.Add(indent.Length);
}
/// <summary>
/// Remove the last indent that was added with PushIndent
/// </summary>
public string PopIndent()
{
string returnValue = "";
if ((this.indentLengths.Count > 0))
{
int indentLength = this.indentLengths[(this.indentLengths.Count - 1)];
this.indentLengths.RemoveAt((this.indentLengths.Count - 1));
if ((indentLength > 0))
{
returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength));
this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength));
}
}
return returnValue;
}
/// <summary>
/// Remove any indentation
/// </summary>
public void ClearIndent()
{
this.indentLengths.Clear();
this.currentIndentField = "";
}
#endregion
#region ToString Helpers
/// <summary>
/// Utility class to produce culture-oriented representation of an object as a string.
/// </summary>
public class ToStringInstanceHelper
{
private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture;
/// <summary>
/// Gets or sets format provider to be used by ToStringWithCulture method.
/// </summary>
public System.IFormatProvider FormatProvider
{
get
{
return this.formatProviderField ;
}
set
{
if ((value != null))
{
this.formatProviderField = value;
}
}
}
/// <summary>
/// This is called from the compile/run appdomain to convert objects within an expression block to a string
/// </summary>
public string ToStringWithCulture(object objectToConvert)
{
if ((objectToConvert == null))
{
throw new global::System.ArgumentNullException("objectToConvert");
}
System.Type t = objectToConvert.GetType();
System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] {
typeof(System.IFormatProvider)});
if ((method == null))
{
return objectToConvert.ToString();
}
else
{
return ((string)(method.Invoke(objectToConvert, new object[] {
this.formatProviderField })));
}
}
}
private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper();
/// <summary>
/// Helper to produce culture-oriented representation of an object as a string
/// </summary>
public ToStringInstanceHelper ToStringHelper
{
get
{
return this.toStringHelperField;
}
}
#endregion
}
#endregion
}

Просмотреть файл

@ -0,0 +1,125 @@
<#@ template hostSpecific="true" linePragmas="false" #>
<#@ parameter type="Microsoft.DotNet.Tools.Scaffold.AspNet.Models.EfControllerModel" name="Model" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Linq" #>
<#
string modelName = Model.ModelInfo.ModelTypeName;
string modelNameUpperVariant = modelName.ToUpperInvariant();
string modelNameLowerVariant = modelName.ToLowerInvariant();
string pluralModel = Model.ModelInfo.ModelTypePluralName.ToUpperInvariant();
string dbContextNamespace = string.IsNullOrEmpty(Model.DbContextInfo.DbContextNamespace) ? string.Empty : Model.DbContextInfo.DbContextNamespace;
string dbContextName = Model.DbContextInfo.DbContextClassName;
string entitySetName = Model.DbContextInfo.EntitySetVariableName ?? modelName;
string modelNamespace = Model.ModelInfo.ModelNamespace;
#>
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
<#
if (!string.IsNullOrEmpty(modelNamespace))
{
#>using <#= modelNamespace #>;
<# }
#>
<#
if (!string.IsNullOrEmpty(dbContextNamespace))
{
#>using <#= dbContextNamespace #>;
<# }
#>
[Route("api/[controller]")]
[ApiController]
public class <#= Model.ControllerName #> : ControllerBase
{
private readonly <#= dbContextName #> _context;
public <#= Model.ControllerName #>(<#= dbContextName #> context)
{
_context = context;
}
// GET: api/<#= modelName #>
[HttpGet]
public async Task<ActionResult<IEnumerable<<#= modelName #>>>> Get<#= modelName #>()
{
return await _context.<#= entitySetName #>.ToListAsync();
}
// GET: api/<#= modelName #>/5
[HttpGet("{id}")]
public async Task<ActionResult<<#= modelName #>>> Get<#= modelName #>(int id)
{
var <#= modelNameLowerVariant #> = await _context.<#= entitySetName #>.FindAsync(id);
if (<#= modelNameLowerVariant #> == null)
{
return NotFound();
}
return <#= modelNameLowerVariant #>;
}
// PUT: api/<#= modelName #>/5
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
[HttpPut("{id}")]
public async Task<IActionResult> Put<#= modelName #>(int id, <#= modelName #> <#= modelNameLowerVariant #>)
{
if (id != <#= modelNameLowerVariant #>.ID)
{
return BadRequest();
}
_context.Entry(<#= modelNameLowerVariant #>).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!<#= modelName #>Exists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
// POST: api/<#= modelName #>
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
[HttpPost]
public async Task<ActionResult<<#= modelName #>>> Post<#= modelName #>(<#= modelName #> <#= modelNameLowerVariant #>)
{
_context.<#= entitySetName #>.Add(<#= modelNameLowerVariant #>);
await _context.SaveChangesAsync();
return CreatedAtAction("Get<#= modelName #>", new { id = <#= modelNameLowerVariant #>.ID }, <#= modelNameLowerVariant #>);
}
// DELETE: api/<#= modelName #>/5
[HttpDelete("{id}")]
public async Task<IActionResult> Delete<#= modelName #>(int id)
{
var <#= modelNameLowerVariant #> = await _context.<#= entitySetName #>.FindAsync(id);
if (<#= modelNameLowerVariant #> == null)
{
return NotFound();
}
_context.<#= entitySetName #>.Remove(<#= modelNameLowerVariant #>);
await _context.SaveChangesAsync();
return NoContent();
}
private bool <#= modelName #>Exists(int id)
{
return _context.<#= entitySetName #>.Any(e => e.ID == id);
}
}

Просмотреть файл

@ -0,0 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.DotNet.Scaffolding.TextTemplating;
namespace Microsoft.DotNet.Tools.Scaffold.AspNet.Templates.EfController;
public partial class MvcEfController : ITextTransformation
{
}

Просмотреть файл

@ -0,0 +1,535 @@
// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version: 17.0.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
// ------------------------------------------------------------------------------
namespace Microsoft.DotNet.Tools.Scaffold.AspNet.Templates.EfController
{
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System;
/// <summary>
/// Class to produce the template output
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
public partial class MvcEfController : MvcEfControllerBase
{
/// <summary>
/// Create the template output
/// </summary>
public virtual string TransformText()
{
string modelName = Model.ModelInfo.ModelTypeName;
string modelNameUpperVariant = modelName.ToUpperInvariant();
string pluralModel = Model.ModelInfo.ModelTypePluralName.ToUpperInvariant();
string modelNameLowerInv = modelName.ToLowerInvariant();
string dbContextNamespace = string.IsNullOrEmpty(Model.DbContextInfo.DbContextNamespace) ? string.Empty : Model.DbContextInfo.DbContextNamespace;
string dbContextName = Model.DbContextInfo.DbContextClassName;
string entitySetName = Model.DbContextInfo.EntitySetVariableName ?? modelName;
string modelNamespace = Model.ModelInfo.ModelNamespace;
string primaryKeyName = Model.ModelInfo.PrimaryKeyName;
string primaryKeyNameLowerCase = primaryKeyName.ToLowerInvariant();
string primaryKeyShortTypeName = Model.ModelInfo.PrimaryKeyShortTypeName;
string primaryKeyType = Model.ModelInfo.PrimaryKeyTypeName;
this.Write("\r\nusing Microsoft.AspNetCore.Mvc;\r\nusing Microsoft.EntityFrameworkCore;\r\n");
if (!string.IsNullOrEmpty(modelNamespace))
{
this.Write("using ");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNamespace));
this.Write(";\r\n");
}
if (!string.IsNullOrEmpty(dbContextNamespace))
{
this.Write("using ");
this.Write(this.ToStringHelper.ToStringWithCulture(dbContextNamespace));
this.Write(";\r\n");
}
this.Write("\r\npublic class ");
this.Write(this.ToStringHelper.ToStringWithCulture(Model.ControllerName));
this.Write(" : Controller\r\n{\r\n private readonly ");
this.Write(this.ToStringHelper.ToStringWithCulture(dbContextName));
this.Write(" _context;\r\n\r\n public ");
this.Write(this.ToStringHelper.ToStringWithCulture(Model.ControllerName));
this.Write("(");
this.Write(this.ToStringHelper.ToStringWithCulture(dbContextName));
this.Write(" context)\r\n {\r\n _context = context;\r\n }\r\n\r\n // GET: ");
this.Write(this.ToStringHelper.ToStringWithCulture(pluralModel));
this.Write("\r\n public async Task<IActionResult> Index() \r\n {\r\n return View(aw" +
"ait _context.");
this.Write(this.ToStringHelper.ToStringWithCulture(entitySetName));
this.Write(".ToListAsync());\r\n }\r\n\r\n // GET: ");
this.Write(this.ToStringHelper.ToStringWithCulture(pluralModel));
this.Write("/Details/5\r\n public async Task<IActionResult> Details(int? id)\r\n {\r\n " +
" if (id == null)\r\n {\r\n return NotFound();\r\n }\r\n\r\n " +
" var ");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerInv));
this.Write(" = await _context.");
this.Write(this.ToStringHelper.ToStringWithCulture(entitySetName));
this.Write("\r\n .FirstOrDefaultAsync(m => m.ID == id);\r\n if (");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerInv));
this.Write(" == null)\r\n {\r\n return NotFound();\r\n }\r\n\r\n return" +
" View(");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerInv));
this.Write(");\r\n }\r\n\r\n // GET: ");
this.Write(this.ToStringHelper.ToStringWithCulture(pluralModel));
this.Write("/Create\r\n public IActionResult Create()\r\n {\r\n return View();\r\n }\r" +
"\n\r\n // POST: ");
this.Write(this.ToStringHelper.ToStringWithCulture(pluralModel));
this.Write(@"/Create
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind(""ID,Title,ReleaseDate,Genre,Price"")] ");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write(" movie)\r\n {\r\n if (ModelState.IsValid)\r\n {\r\n _context." +
"Add(");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerInv));
this.Write(");\r\n await _context.SaveChangesAsync();\r\n return RedirectTo" +
"Action(nameof(Index));\r\n }\r\n return View(");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerInv));
this.Write(");\r\n }\r\n\r\n // GET: ");
this.Write(this.ToStringHelper.ToStringWithCulture(pluralModel));
this.Write("/Edit/5\r\n public async Task<IActionResult> Edit(int? id)\r\n {\r\n if (i" +
"d == null)\r\n {\r\n return NotFound();\r\n }\r\n\r\n var " +
"");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerInv));
this.Write(" = await _context.");
this.Write(this.ToStringHelper.ToStringWithCulture(entitySetName));
this.Write(".FindAsync(id);\r\n if (");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerInv));
this.Write(" == null)\r\n {\r\n return NotFound();\r\n }\r\n return V" +
"iew(");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerInv));
this.Write(");\r\n }\r\n\r\n // POST: ");
this.Write(this.ToStringHelper.ToStringWithCulture(pluralModel));
this.Write(@"/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind(""ID,Title,ReleaseDate,Genre,Price"")] ");
this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
this.Write(" movie)\r\n {\r\n if (id != ");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerInv));
this.Write(".ID)\r\n {\r\n return NotFound();\r\n }\r\n\r\n if (ModelSt" +
"ate.IsValid)\r\n {\r\n try\r\n {\r\n _contex" +
"t.Update(");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerInv));
this.Write(");\r\n await _context.SaveChangesAsync();\r\n }\r\n " +
" catch (DbUpdateConcurrencyException)\r\n {\r\n if (!");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameUpperVariant));
this.Write("Exists(");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerInv));
this.Write(@".ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerInv));
this.Write(");\r\n }\r\n\r\n // GET: ");
this.Write(this.ToStringHelper.ToStringWithCulture(pluralModel));
this.Write("/Delete/5\r\n public async Task<IActionResult> Delete(int? id)\r\n {\r\n i" +
"f (id == null)\r\n {\r\n return NotFound();\r\n }\r\n\r\n " +
"var ");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerInv));
this.Write(" = await _context.");
this.Write(this.ToStringHelper.ToStringWithCulture(entitySetName));
this.Write("\r\n .FirstOrDefaultAsync(m => m.ID == id);\r\n if (");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerInv));
this.Write(" == null)\r\n {\r\n return NotFound();\r\n }\r\n\r\n return" +
" View(");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerInv));
this.Write(");\r\n }\r\n\r\n // POST: ");
this.Write(this.ToStringHelper.ToStringWithCulture(pluralModel));
this.Write("/Delete/5\r\n [HttpPost, ActionName(\"Delete\")]\r\n [ValidateAntiForgeryToken]\r\n" +
" public async Task<IActionResult> DeleteConfirmed(int id)\r\n {\r\n var" +
" ");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerInv));
this.Write(" = await _context.");
this.Write(this.ToStringHelper.ToStringWithCulture(entitySetName));
this.Write(".FindAsync(id);\r\n if (");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerInv));
this.Write(" != null)\r\n {\r\n _context.");
this.Write(this.ToStringHelper.ToStringWithCulture(entitySetName));
this.Write(".Remove(");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameLowerInv));
this.Write(");\r\n }\r\n\r\n await _context.SaveChangesAsync();\r\n return Redir" +
"ectToAction(nameof(Index));\r\n }\r\n\r\n private bool ");
this.Write(this.ToStringHelper.ToStringWithCulture(modelNameUpperVariant));
this.Write("Exists(int id)\r\n {\r\n return _context.");
this.Write(this.ToStringHelper.ToStringWithCulture(entitySetName));
this.Write(".Any(e => e.ID == id);\r\n }\r\n}\r\n");
return this.GenerationEnvironment.ToString();
}
private global::Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost hostValue;
/// <summary>
/// The current host for the text templating engine
/// </summary>
public virtual global::Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost Host
{
get
{
return this.hostValue;
}
set
{
this.hostValue = value;
}
}
private global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.EfControllerModel _ModelField;
/// <summary>
/// Access the Model parameter of the template.
/// </summary>
private global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.EfControllerModel Model
{
get
{
return this._ModelField;
}
}
/// <summary>
/// Initialize the template
/// </summary>
public virtual void Initialize()
{
if ((this.Errors.HasErrors == false))
{
bool ModelValueAcquired = false;
if (this.Session.ContainsKey("Model"))
{
this._ModelField = ((global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.EfControllerModel)(this.Session["Model"]));
ModelValueAcquired = true;
}
if ((ModelValueAcquired == false))
{
string parameterValue = this.Host.ResolveParameterValue("Property", "PropertyDirectiveProcessor", "Model");
if ((string.IsNullOrEmpty(parameterValue) == false))
{
global::System.ComponentModel.TypeConverter tc = global::System.ComponentModel.TypeDescriptor.GetConverter(typeof(global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.EfControllerModel));
if (((tc != null)
&& tc.CanConvertFrom(typeof(string))))
{
this._ModelField = ((global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.EfControllerModel)(tc.ConvertFrom(parameterValue)));
ModelValueAcquired = true;
}
else
{
this.Error("The type \'Microsoft.DotNet.Tools.Scaffold.AspNet.Models.EfControllerModel\' of the" +
" parameter \'Model\' did not match the type of the data passed to the template.");
}
}
}
if ((ModelValueAcquired == false))
{
object data = global::Microsoft.DotNet.Scaffolding.TextTemplating.CallContext.LogicalGetData("Model");
if ((data != null))
{
this._ModelField = ((global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.EfControllerModel)(data));
}
}
}
}
}
#region Base class
/// <summary>
/// Base class for this transformation
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
public class MvcEfControllerBase
{
#region Fields
private global::System.Text.StringBuilder generationEnvironmentField;
private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField;
private global::System.Collections.Generic.List<int> indentLengthsField;
private string currentIndentField = "";
private bool endsWithNewline;
private global::System.Collections.Generic.IDictionary<string, object> sessionField;
#endregion
#region Properties
/// <summary>
/// The string builder that generation-time code is using to assemble generated output
/// </summary>
public System.Text.StringBuilder GenerationEnvironment
{
get
{
if ((this.generationEnvironmentField == null))
{
this.generationEnvironmentField = new global::System.Text.StringBuilder();
}
return this.generationEnvironmentField;
}
set
{
this.generationEnvironmentField = value;
}
}
/// <summary>
/// The error collection for the generation process
/// </summary>
public System.CodeDom.Compiler.CompilerErrorCollection Errors
{
get
{
if ((this.errorsField == null))
{
this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection();
}
return this.errorsField;
}
}
/// <summary>
/// A list of the lengths of each indent that was added with PushIndent
/// </summary>
private System.Collections.Generic.List<int> indentLengths
{
get
{
if ((this.indentLengthsField == null))
{
this.indentLengthsField = new global::System.Collections.Generic.List<int>();
}
return this.indentLengthsField;
}
}
/// <summary>
/// Gets the current indent we use when adding lines to the output
/// </summary>
public string CurrentIndent
{
get
{
return this.currentIndentField;
}
}
/// <summary>
/// Current transformation session
/// </summary>
public virtual global::System.Collections.Generic.IDictionary<string, object> Session
{
get
{
return this.sessionField;
}
set
{
this.sessionField = value;
}
}
#endregion
#region Transform-time helpers
/// <summary>
/// Write text directly into the generated output
/// </summary>
public void Write(string textToAppend)
{
if (string.IsNullOrEmpty(textToAppend))
{
return;
}
// If we're starting off, or if the previous text ended with a newline,
// we have to append the current indent first.
if (((this.GenerationEnvironment.Length == 0)
|| this.endsWithNewline))
{
this.GenerationEnvironment.Append(this.currentIndentField);
this.endsWithNewline = false;
}
// Check if the current text ends with a newline
if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture))
{
this.endsWithNewline = true;
}
// This is an optimization. If the current indent is "", then we don't have to do any
// of the more complex stuff further down.
if ((this.currentIndentField.Length == 0))
{
this.GenerationEnvironment.Append(textToAppend);
return;
}
// Everywhere there is a newline in the text, add an indent after it
textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField));
// If the text ends with a newline, then we should strip off the indent added at the very end
// because the appropriate indent will be added when the next time Write() is called
if (this.endsWithNewline)
{
this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length));
}
else
{
this.GenerationEnvironment.Append(textToAppend);
}
}
/// <summary>
/// Write text directly into the generated output
/// </summary>
public void WriteLine(string textToAppend)
{
this.Write(textToAppend);
this.GenerationEnvironment.AppendLine();
this.endsWithNewline = true;
}
/// <summary>
/// Write formatted text directly into the generated output
/// </summary>
public void Write(string format, params object[] args)
{
this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
}
/// <summary>
/// Write formatted text directly into the generated output
/// </summary>
public void WriteLine(string format, params object[] args)
{
this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
}
/// <summary>
/// Raise an error
/// </summary>
public void Error(string message)
{
System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
error.ErrorText = message;
this.Errors.Add(error);
}
/// <summary>
/// Raise a warning
/// </summary>
public void Warning(string message)
{
System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
error.ErrorText = message;
error.IsWarning = true;
this.Errors.Add(error);
}
/// <summary>
/// Increase the indent
/// </summary>
public void PushIndent(string indent)
{
if ((indent == null))
{
throw new global::System.ArgumentNullException("indent");
}
this.currentIndentField = (this.currentIndentField + indent);
this.indentLengths.Add(indent.Length);
}
/// <summary>
/// Remove the last indent that was added with PushIndent
/// </summary>
public string PopIndent()
{
string returnValue = "";
if ((this.indentLengths.Count > 0))
{
int indentLength = this.indentLengths[(this.indentLengths.Count - 1)];
this.indentLengths.RemoveAt((this.indentLengths.Count - 1));
if ((indentLength > 0))
{
returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength));
this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength));
}
}
return returnValue;
}
/// <summary>
/// Remove any indentation
/// </summary>
public void ClearIndent()
{
this.indentLengths.Clear();
this.currentIndentField = "";
}
#endregion
#region ToString Helpers
/// <summary>
/// Utility class to produce culture-oriented representation of an object as a string.
/// </summary>
public class ToStringInstanceHelper
{
private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture;
/// <summary>
/// Gets or sets format provider to be used by ToStringWithCulture method.
/// </summary>
public System.IFormatProvider FormatProvider
{
get
{
return this.formatProviderField ;
}
set
{
if ((value != null))
{
this.formatProviderField = value;
}
}
}
/// <summary>
/// This is called from the compile/run appdomain to convert objects within an expression block to a string
/// </summary>
public string ToStringWithCulture(object objectToConvert)
{
if ((objectToConvert == null))
{
throw new global::System.ArgumentNullException("objectToConvert");
}
System.Type t = objectToConvert.GetType();
System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] {
typeof(System.IFormatProvider)});
if ((method == null))
{
return objectToConvert.ToString();
}
else
{
return ((string)(method.Invoke(objectToConvert, new object[] {
this.formatProviderField })));
}
}
}
private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper();
/// <summary>
/// Helper to produce culture-oriented representation of an object as a string
/// </summary>
public ToStringInstanceHelper ToStringHelper
{
get
{
return this.toStringHelperField;
}
}
#endregion
}
#endregion
}

Просмотреть файл

@ -0,0 +1,179 @@
<#@ template hostSpecific="true" linePragmas="false" #>
<#@ parameter type="Microsoft.DotNet.Tools.Scaffold.AspNet.Models.EfControllerModel" name="Model" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Linq" #>
<#
string modelName = Model.ModelInfo.ModelTypeName;
string modelNameUpperVariant = modelName.ToUpperInvariant();
string pluralModel = Model.ModelInfo.ModelTypePluralName.ToUpperInvariant();
string modelNameLowerInv = modelName.ToLowerInvariant();
string dbContextNamespace = string.IsNullOrEmpty(Model.DbContextInfo.DbContextNamespace) ? string.Empty : Model.DbContextInfo.DbContextNamespace;
string dbContextName = Model.DbContextInfo.DbContextClassName;
string entitySetName = Model.DbContextInfo.EntitySetVariableName ?? modelName;
string modelNamespace = Model.ModelInfo.ModelNamespace;
string primaryKeyName = Model.ModelInfo.PrimaryKeyName;
string primaryKeyNameLowerCase = primaryKeyName.ToLowerInvariant();
string primaryKeyShortTypeName = Model.ModelInfo.PrimaryKeyShortTypeName;
string primaryKeyType = Model.ModelInfo.PrimaryKeyTypeName;
#>
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
<#
if (!string.IsNullOrEmpty(modelNamespace))
{
#>using <#= modelNamespace #>;
<# }
#>
<#
if (!string.IsNullOrEmpty(dbContextNamespace))
{
#>using <#= dbContextNamespace #>;
<# }
#>
public class <#= Model.ControllerName #> : Controller
{
private readonly <#= dbContextName #> _context;
public <#= Model.ControllerName #>(<#= dbContextName #> context)
{
_context = context;
}
// GET: <#= pluralModel #>
public async Task<IActionResult> Index()
{
return View(await _context.<#= entitySetName #>.ToListAsync());
}
// GET: <#= pluralModel #>/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var <#= modelNameLowerInv #> = await _context.<#= entitySetName #>
.FirstOrDefaultAsync(m => m.ID == id);
if (<#= modelNameLowerInv #> == null)
{
return NotFound();
}
return View(<#= modelNameLowerInv #>);
}
// GET: <#= pluralModel #>/Create
public IActionResult Create()
{
return View();
}
// POST: <#= pluralModel #>/Create
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("ID,Title,ReleaseDate,Genre,Price")] <#= modelName #> movie)
{
if (ModelState.IsValid)
{
_context.Add(<#= modelNameLowerInv #>);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(<#= modelNameLowerInv #>);
}
// GET: <#= pluralModel #>/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var <#= modelNameLowerInv #> = await _context.<#= entitySetName #>.FindAsync(id);
if (<#= modelNameLowerInv #> == null)
{
return NotFound();
}
return View(<#= modelNameLowerInv #>);
}
// POST: <#= pluralModel #>/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Title,ReleaseDate,Genre,Price")] <#= modelName #> movie)
{
if (id != <#= modelNameLowerInv #>.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(<#= modelNameLowerInv #>);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!<#= modelNameUpperVariant #>Exists(<#= modelNameLowerInv #>.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(<#= modelNameLowerInv #>);
}
// GET: <#= pluralModel #>/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var <#= modelNameLowerInv #> = await _context.<#= entitySetName #>
.FirstOrDefaultAsync(m => m.ID == id);
if (<#= modelNameLowerInv #> == null)
{
return NotFound();
}
return View(<#= modelNameLowerInv #>);
}
// POST: <#= pluralModel #>/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var <#= modelNameLowerInv #> = await _context.<#= entitySetName #>.FindAsync(id);
if (<#= modelNameLowerInv #> != null)
{
_context.<#= entitySetName #>.Remove(<#= modelNameLowerInv #>);
}
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool <#= modelNameUpperVariant #>Exists(int id)
{
return _context.<#= entitySetName #>.Any(e => e.ID == id);
}
}

Просмотреть файл

@ -24,10 +24,14 @@
<None Pack="true" Include="$(RepoRoot)src\dotnet-scaffolding\dotnet-scaffold-aspnet\Templates\*\*.tt" PackagePath="Templates\" />
<None Pack="true" Include="$(RepoRoot)src\dotnet-scaffolding\Microsoft.DotNet.Scaffolding.TextTemplating\DbContext\*.tt" PackagePath="Templates\DbContext\" />
<None Pack="true" Include="CodeModificationConfigs\*.json" PackagePath="CodeModificationConfigs\" />
<None Pack="true" Include="README.md" PackagePath="\"/>
<None Pack="true" Include="README.md" PackagePath="\" />
</ItemGroup>
<ItemGroup>
<None Update="Templates\EfController\ApiEfController.tt">
<Generator>TextTemplatingFilePreprocessor</Generator>
<LastGenOutput>ApiEfController.cs</LastGenOutput>
</None>
<None Update="Templates\BlazorCrud\Create.tt">
<LastGenOutput>Create.cs</LastGenOutput>
<Generator>TextTemplatingFilePreprocessor</Generator>
@ -55,6 +59,11 @@
</ItemGroup>
<ItemGroup>
<Compile Update="Templates\EfController\ApiEfController.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>ApiEfController.tt</DependentUpon>
</Compile>
<Compile Update="Templates\BlazorCrud\Create.cs">
<DependentUpon>Create.tt</DependentUpon>
<DesignTime>True</DesignTime>
@ -90,6 +99,11 @@
<AutoGen>True</AutoGen>
<DependentUpon>MinimalApiEf.tt</DependentUpon>
</Compile>
<Compile Update="Templates\EfController\MvcEfController.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>MvcEfController.tt</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
@ -97,6 +111,9 @@
<Generator>TextTemplatingFilePreprocessor</Generator>
<LastGenOutput>MinimalApiEf.cs</LastGenOutput>
</None>
<None Update="Templates\EfController\MvcEfController.tt">
<Generator>TextTemplatingFilePreprocessor</Generator>
<LastGenOutput>MvcEfController.cs</LastGenOutput>
</None>
</ItemGroup>
</Project>