Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
<MicrosoftAspNetCoreIdentityUIPackageVersion>7.0.3</MicrosoftAspNetCoreIdentityUIPackageVersion>
</PropertyGroup>
<PropertyGroup>
<VersionPrefix>7.0.3</VersionPrefix>
<VersionPrefix>7.0.4</VersionPrefix>
<PreReleaseVersionLabel>rtm</PreReleaseVersionLabel>
<IncludeSourceRevisionInInformationalVersion>False</IncludeSourceRevisionInInformationalVersion>
<IsServicingBuild Condition="'$(PreReleaseVersionLabel)' == 'servicing'">true</IsServicingBuild>
Expand Down
2 changes: 1 addition & 1 deletion scripts/install-aspnet-codegenerator.cmd
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
set VERSION=8.0.0-dev
set VERSION=7.0.4
set DEFAULT_NUPKG_PATH=%userprofile%\.nuget\packages
set SRC_DIR=%cd%
set NUPKG=artifacts/packages/Debug/Shipping/
Expand Down
2 changes: 1 addition & 1 deletion scripts/install-aspnet-codegenerator.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

VERSION=8.0.0-dev
VERSION=7.0.4
DEFAULT_NUPKG_PATH=~/.nuget/packages
SRC_DIR=$(pwd)
echo $SRC_DIR
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -744,14 +744,9 @@ private void ValidateRequiredDependencies()
var dependencies = new HashSet<string>()
{
"Microsoft.AspNetCore.Identity.UI",
"Microsoft.EntityFrameworkCore.Design"
EfConstants.EfToolsPackageName
};

const string EfDesignPackageName = "Microsoft.EntityFrameworkCore.Design";
var isEFDesignPackagePresent = _projectContext
.PackageDependencies
.Any(package => package.Name.Equals(EfDesignPackageName, StringComparison.OrdinalIgnoreCase));

var missingPackages = dependencies.Where(d => !_projectContext.PackageDependencies.Any(p => p.Name.Equals(d, StringComparison.OrdinalIgnoreCase)));
if (CalledFromCommandline && missingPackages.Any())
{
Expand Down
20 changes: 10 additions & 10 deletions src/Scaffolding/VS.Web.CG.Mvc/Minimal Api/MinimalApiGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class MinimalApiGenerator : ICodeGenerator
private IModelTypesLocator ModelTypesLocator { get; set; }
private IFileSystem FileSystem { get; set; }
private IProjectContext ProjectContext { get; set; }
private IEntityFrameworkService EntityFrameworkService { get; set;}
private IEntityFrameworkService EntityFrameworkService { get; set; }
private ICodeGeneratorActionsService CodeGeneratorActionsService { get; set; }
private Workspace Workspace { get; set; }
private ConsoleLogger ConsoleLogger { get; set; }
Expand Down Expand Up @@ -74,7 +74,7 @@ public async Task GenerateCode(MinimalApiGeneratorCommandLineModel model)
EntityFrameworkService,
ModelTypesLocator,
Logger,
areaName : string.Empty);
areaName: string.Empty);

if (!string.IsNullOrEmpty(modelTypeAndContextModel.DbContextFullName) && CalledFromCommandline)
{
Expand All @@ -85,7 +85,7 @@ public async Task GenerateCode(MinimalApiGeneratorCommandLineModel model)
{
ValidateOpenApiDependencies(ProjectContext.PackageDependencies);
}

var templateModel = new MinimalApiModel(modelTypeAndContextModel.ModelType, modelTypeAndContextModel.DbContextFullName, model.EndpintsClassName)
{
EndpointsName = model.EndpintsClassName,
Expand Down Expand Up @@ -116,7 +116,7 @@ public async Task GenerateCode(MinimalApiGeneratorCommandLineModel model)
}
}
//execute CodeGeneratorActionsService.AddFileFromTemplateAsync to add endpoints file.
else
else
{
//Add endpoints file with endpoints class since it does not exist.
ValidateModel(model);
Expand Down Expand Up @@ -178,7 +178,7 @@ internal async Task AddEndpointsMethod(string membersBlockText, string endpoints
{
usings.Add("Microsoft.AspNetCore.Http.HttpResults");
}
var endpointsCodeFile = new CodeFile { Usings = usings.ToArray()};
var endpointsCodeFile = new CodeFile { Usings = usings.ToArray() };
var docBuilder = new DocumentBuilder(docEditor, endpointsCodeFile, ConsoleLogger);
var newRoot = docBuilder.AddUsings(new CodeChangeOptions());
var classNode = newRoot.DescendantNodes().FirstOrDefault(node => node is ClassDeclarationSyntax classDeclarationSyntax && classDeclarationSyntax.Identifier.ValueText.Contains(className));
Expand All @@ -196,7 +196,7 @@ internal async Task AddEndpointsMethod(string membersBlockText, string endpoints
classDeclaration = SyntaxFactory.ClassDeclaration($"{templateModel.ModelType.Name}Endpoints")
.WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword)))
.NormalizeWhitespace()
.WithLeadingTrivia(SyntaxFactory.CarriageReturnLineFeed, SyntaxFactory.CarriageReturnLineFeed);
.WithLeadingTrivia(SyntaxFactory.CarriageReturnLineFeed, SyntaxFactory.CarriageReturnLineFeed);
}
var modifiedClass = classDeclaration.AddMembers(
SyntaxFactory.GlobalStatement(SyntaxFactory.ParseStatement(membersBlockText)).WithLeadingTrivia(SyntaxFactory.Tab));
Expand All @@ -212,7 +212,7 @@ internal async Task AddEndpointsMethod(string membersBlockText, string endpoints
{
newRoot = newRoot.ReplaceNode(classNode, modifiedClass);
}

docEditor.ReplaceNode(docRoot, newRoot);
var classFileSourceTxt = await docEditor.GetChangedDocument()?.GetTextAsync();
var classFileTxt = classFileSourceTxt?.ToString();
Expand Down Expand Up @@ -323,7 +323,7 @@ internal async Task ModifyProgramCs(MinimalApiModel templateModel)
newRoot = newRoot?.ReplaceNode(mainMethod.Body, updatedMethod);
}
}

if (templateModel.OpenAPI)
{
var builderVariable = ProjectModifierHelper.GetBuilderVariableIdentifierTransformation(newRoot.Members);
Expand All @@ -336,7 +336,7 @@ internal async Task ModifyProgramCs(MinimalApiModel templateModel)
{
filteredChanges = DocumentBuilder.AddLeadingTriviaSpaces(filteredChanges, spaces: 12);
var mainMethod = DocumentBuilder.GetMethodFromSyntaxRoot(newRoot, Main);
{
{
var updatedMethod = DocumentBuilder.ApplyChangesToMethod(mainMethod.Body, filteredChanges);
newRoot = newRoot?.ReplaceNode(mainMethod.Body, updatedMethod);
}
Expand Down Expand Up @@ -390,7 +390,7 @@ private void ValidateOpenApiDependencies(IEnumerable<DependencyDescription> pack
string.Format(MessageStrings.InstallPackagesForScaffoldingIdentity, string.Join(",", missingPackages)));
}
}

private string GetMinimalApiCodeModifierConfig()
{
string jsonText = string.Empty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
string updateModel = $"Update{@modelName}";
string dbContextName = Model.ContextTypeName;
var entitySetName = Model.ModelMetadata.EntitySetName;
var entitySetNoTracking = $"{entitySetName}.AsNoTracking()";
var entityProperties = Model.ModelMetadata.Properties;
var primaryKeyName = Model.ModelMetadata.PrimaryKeys[0].PropertyName;
var primaryKeyNameLowerCase = primaryKeyName.ToLowerInvariant();
var primaryKeyShortTypeName = Model.ModelMetadata.PrimaryKeys[0].ShortTypeName;
Expand All @@ -23,9 +25,10 @@
var remove = $"{@entitySetName}.Remove({@Model.ModelVariable})";
string resultsExtension = Model.UseTypedResults ? "TypedResults" : "Results";
string typedTaskWithNotFound = Model.UseTypedResults ? $"Task<Results<Ok<{@modelName}>, NotFound>>" : "";
string typedTaskWithNoContent = Model.UseTypedResults ? $"Task<Results<NotFound, NoContent>>" : "";
string typedTaskOkNotFound = Model.UseTypedResults ? $"Task<Results<Ok, NotFound>>" : "";
string resultsNotFound = $"{resultsExtension}.NotFound()";
string resultsOkModel = $"{resultsExtension}.Ok(model)";
string resultsOkEmpty = $"{resultsExtension}.Ok()";
string resultsNoContent = $"{resultsExtension}.NoContent()";
string resultsOkModelVariable = $"{resultsExtension}.Ok({@Model.ModelVariable})";
string createdApiVar = string.Format("$\"{0}/{{{1}.{2}}}\",{3}", @routePrefix, @Model.ModelVariable, @primaryKeyName, @Model.ModelVariable);
Expand Down Expand Up @@ -76,7 +79,8 @@ public static class @endPointsClassName

group.MapGet("/{id}", async @typedTaskWithNotFound (@primaryKeyShortTypeName @primaryKeyNameLowerCase, @dbContextName db) =>
{
return await db.@findModel
return await db.@entitySetNoTracking
.FirstOrDefaultAsync(model => model.@primaryKeyName == @primaryKeyNameLowerCase)
is @modelName model
? @resultsOkModel
: @resultsNotFound;
Expand All @@ -95,19 +99,23 @@ public static class @endPointsClassName
@:@builderExtensions;
}

group.MapPut("/{id}", async @typedTaskWithNoContent (@primaryKeyShortTypeName @primaryKeyNameLowerCase, @modelName @Model.ModelVariable, @dbContextName db) =>
group.MapPut("/{id}", async @typedTaskOkNotFound (@primaryKeyShortTypeName @primaryKeyNameLowerCase, @modelName @Model.ModelVariable, @dbContextName db) =>
{
var foundModel = await db.@findModel;

if (foundModel is null)
{
return @resultsNotFound;
}

db.Update(@Model.ModelVariable);
await db.SaveChangesAsync();
var affected = await db.@entitySetName
.Where(model => model.@primaryKeyName == @primaryKeyNameLowerCase)
.ExecuteUpdateAsync(setters => setters
@{
//should be atleast one property (primary key)
foreach(var modelProperty in entityProperties)
{
string modelPropertyName = modelProperty.PropertyName;
string setPropertyString = $".SetProperty(m => m.{modelPropertyName}, {Model.ModelVariable}.{modelPropertyName})";
@:@setPropertyString
}
}
);

return @resultsNoContent;
return affected == 1 ? @resultsOkEmpty : @resultsNotFound;
})
@{
builderExtensions = $".WithName(\"{@updateModel}\")";
Expand Down Expand Up @@ -143,16 +151,13 @@ public static class @endPointsClassName
@:@builderExtensions;
}

group.MapDelete("/{id}", async @typedTaskWithNotFound (@primaryKeyShortTypeName @primaryKeyNameLowerCase, @dbContextName db) =>
group.MapDelete("/{id}", async @typedTaskOkNotFound (@primaryKeyShortTypeName @primaryKeyNameLowerCase, @dbContextName db) =>
{
if (await db.@findModel is @modelName @Model.ModelVariable)
{
db.@remove;
await db.SaveChangesAsync();
return @resultsOkModelVariable;
}
var affected = await db.@entitySetName
.Where(model => model.@primaryKeyName == @primaryKeyNameLowerCase)
.ExecuteDeleteAsync();

return @resultsNotFound;
return affected == 1 ? @resultsOkEmpty : @resultsNotFound;
})
@{
builderExtensions = $".WithName(\"{@deleteModel}\")";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
string modelName = Model.ModelType.Name;
string routePrefix = "/api/" + modelName;
string endPointsClassName = Model.EndpointsName;
string methodName = $"Map{@modelName}Endpoints";
string pluralModel = $"{@modelName}s";
string getAllModels = $"GetAll{@pluralModel}";
string getModelById = $"Get{@modelName}ById";
Expand All @@ -11,6 +12,8 @@
string updateModel = $"Update{@modelName}";
string dbContextName = Model.ContextTypeName;
var entitySetName = Model.ModelMetadata.EntitySetName;
var entitySetNoTracking = $"{entitySetName}.AsNoTracking()";
var entityProperties = Model.ModelMetadata.Properties;
var primaryKeyName = Model.ModelMetadata.PrimaryKeys[0].PropertyName;
var primaryKeyNameLowerCase = primaryKeyName.ToLowerInvariant();
var primaryKeyShortTypeName = Model.ModelMetadata.PrimaryKeys[0].ShortTypeName;
Expand All @@ -22,9 +25,10 @@
var remove = $"{@entitySetName}.Remove({@Model.ModelVariable})";
string resultsExtension = Model.UseTypedResults ? "TypedResults" : "Results";
string typedTaskWithNotFound = Model.UseTypedResults ? $"Task<Results<Ok<{@modelName}>, NotFound>>" : "";
string typedTaskWithNoContent = Model.UseTypedResults ? $"Task<Results<NotFound, NoContent>>" : "";
string typedTaskOkNotFound = Model.UseTypedResults ? $"Task<Results<Ok, NotFound>>" : "";
string resultsNotFound = $"{resultsExtension}.NotFound()";
string resultsOkModel = $"{resultsExtension}.Ok(model)";
string resultsOkEmpty = $"{resultsExtension}.Ok()";
string resultsNoContent = $"{resultsExtension}.NoContent()";
string resultsOkModelVariable = $"{resultsExtension}.Ok({@Model.ModelVariable})";
string createdApiVar = string.Format("$\"{0}/{{{1}.{2}}}\",{3}", @routePrefix, @Model.ModelVariable, @primaryKeyName, @Model.ModelVariable);
Expand Down Expand Up @@ -64,7 +68,8 @@

group.MapGet("/{id}", async @typedTaskWithNotFound (@primaryKeyShortTypeName @primaryKeyNameLowerCase, @dbContextName db) =>
{
return await db.@findModel
return await db.@entitySetNoTracking
.FirstOrDefaultAsync(model => model.@primaryKeyName == @primaryKeyNameLowerCase)
is @modelName model
? @resultsOkModel
: @resultsNotFound;
Expand All @@ -83,19 +88,23 @@
@:@builderExtensions;
}

group.MapPut("/{id}", async @typedTaskWithNoContent (@primaryKeyShortTypeName @primaryKeyNameLowerCase, @modelName @Model.ModelVariable, @dbContextName db) =>
group.MapPut("/{id}", async @typedTaskOkNotFound (@primaryKeyShortTypeName @primaryKeyNameLowerCase, @modelName @Model.ModelVariable, @dbContextName db) =>
{
var foundModel = await db.@findModel;

if (foundModel is null)
{
return @resultsNotFound;
}

db.Update(@Model.ModelVariable);
await db.SaveChangesAsync();
var affected = await db.@entitySetName
.Where(model => model.@primaryKeyName == @primaryKeyNameLowerCase)
.ExecuteUpdateAsync(setters => setters
@{
//should be atleast one property (primary key)
foreach(var modelProperty in entityProperties)
{
string modelPropertyName = modelProperty.PropertyName;
string setPropertyString = $".SetProperty(m => m.{modelPropertyName}, {Model.ModelVariable}.{modelPropertyName})";
@:@setPropertyString
}
}
);

return @resultsNoContent;
return affected == 1 ? @resultsOkEmpty : @resultsNotFound;
})
@{
builderExtensions = $".WithName(\"{@updateModel}\")";
Expand Down Expand Up @@ -131,16 +140,13 @@
@:@builderExtensions;
}

group.MapDelete("/{id}", async @typedTaskWithNotFound (@primaryKeyShortTypeName @primaryKeyNameLowerCase, @dbContextName db) =>
group.MapDelete("/{id}", async @typedTaskOkNotFound (@primaryKeyShortTypeName @primaryKeyNameLowerCase, @dbContextName db) =>
{
if (await db.@findModel is @modelName @Model.ModelVariable)
{
db.@remove;
await db.SaveChangesAsync();
return @resultsOkModelVariable;
}
var affected = await db.@entitySetName
.Where(model => model.@primaryKeyName == @primaryKeyNameLowerCase)
.ExecuteDeleteAsync();

return @resultsNotFound;
return affected == 1 ? @resultsOkEmpty : @resultsNotFound;
})
@{
builderExtensions = $".WithName(\"{@deleteModel}\")";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ internal static class EFValidationUtil
internal static void ValidateEFDependencies(IEnumerable<DependencyDescription> dependencies, DbProvider dataContextType)
{
var isEFDesignPackagePresent = dependencies
.Any(package => package.Name.Equals(EfConstants.EfDesignPackageName, StringComparison.OrdinalIgnoreCase));
.Any(package => package.Name.Equals(EfConstants.EfToolsPackageName, StringComparison.OrdinalIgnoreCase));

if (!isEFDesignPackagePresent)
{
throw new InvalidOperationException(
string.Format(MessageStrings.InstallEfPackages, $"{EfConstants.EfDesignPackageName}"));
string.Format(MessageStrings.InstallEfPackages, $"{EfConstants.EfToolsPackageName}"));
}

if (EfConstants.EfPackagesDict.TryGetValue(dataContextType, out var dbProviderPackageName))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public static class EfConstants
public static string SQLite = DbProvider.SQLite.ToString();
public static string CosmosDb = DbProvider.CosmosDb.ToString();
public static string Postgres = DbProvider.Postgres.ToString();
public const string EfDesignPackageName = "Microsoft.EntityFrameworkCore.Design";
public const string EfToolsPackageName = "Microsoft.EntityFrameworkCore.Tools";
public const string SqlServerPackageName = "Microsoft.EntityFrameworkCore.SqlServer";
public const string SqlitePackageName = "Microsoft.EntityFrameworkCore.Sqlite";
public const string CosmosPakcageName = "Microsoft.EntityFrameworkCore.Cosmos";
Expand Down