+
<#= requiredSpanAttributeHtml #>
- <<#= inputTypeName #> id="<#= modelPropertyNameLowercase #>" @bind-Value="<#= modelName #>.<#= modelPropertyName #>" class="<#= inputClass #>" <#= requiredHtml #>/>
+ <<#= inputTypeName #> id="<#= modelPropertyNameLowercase #>" @bind-Value="<#= modelName #>.<#= modelPropertyName #>" class="<#= inputClass #>" <#= ariaRequiredAttributeHtml #>/>
<# } #>
diff --git a/src/Scaffolding/VS.Web.CG.Mvc/Templates/RazorPageGenerator/Bootstrap5/Create.cshtml b/src/Scaffolding/VS.Web.CG.Mvc/Templates/RazorPageGenerator/Bootstrap5/Create.cshtml
index 1bbb51cd9..60e3389c0 100644
--- a/src/Scaffolding/VS.Web.CG.Mvc/Templates/RazorPageGenerator/Bootstrap5/Create.cshtml
+++ b/src/Scaffolding/VS.Web.CG.Mvc/Templates/RazorPageGenerator/Bootstrap5/Create.cshtml
@@ -48,14 +48,15 @@
foreach (var property in Model.ModelMetadata.Properties)
{
var sixteenWhitespace = new string(' ', 16);
- var propertyRequiredText = property.IsRequired ? $"\n{sixteenWhitespace}
*" : string.Empty;
+ var propertyRequiredText = property.IsRequired ? $"\r\n{sixteenWhitespace}
*" : string.Empty;
+ var ariaRequiredAttributeHtml = property.IsRequired ? "aria-required=\"true\"" : string.Empty;
if (property.Scaffold && !property.IsAutoGenerated && !property.IsReadOnly)
{
if (property.IsForeignKey)
{
@:
@propertyRequiredText
@:
- @:
+ @:
@:
continue;
}
@@ -65,7 +66,7 @@
{
@:
@propertyRequiredText
@:
@:
}
@@ -73,7 +74,7 @@
{
@:
@propertyRequiredText
@:
- @:
+ @:
@:
@:
}
@@ -81,7 +82,7 @@
{
@:
@propertyRequiredText
@:
- @:
+ @:
@:
@:
}
@@ -89,7 +90,7 @@
{
@:
@propertyRequiredText
@:
- @:
+ @:
@:
@:
}
diff --git a/src/Scaffolding/VS.Web.CG.Mvc/Templates/RazorPageGenerator/Bootstrap5/Edit.cshtml b/src/Scaffolding/VS.Web.CG.Mvc/Templates/RazorPageGenerator/Bootstrap5/Edit.cshtml
index efa8823a6..2be437dde 100644
--- a/src/Scaffolding/VS.Web.CG.Mvc/Templates/RazorPageGenerator/Bootstrap5/Edit.cshtml
+++ b/src/Scaffolding/VS.Web.CG.Mvc/Templates/RazorPageGenerator/Bootstrap5/Edit.cshtml
@@ -48,7 +48,8 @@
foreach (PropertyMetadata property in Model.ModelMetadata.Properties)
{
var sixteenWhitespace = new string(' ', 16);
- var propertyRequiredText = property.IsRequired ? $"\n{sixteenWhitespace}
*" : string.Empty;
+ var propertyRequiredText = property.IsRequired ? "\r\n
*" : string.Empty;
+ var ariaRequiredAttributeHtml = property.IsRequired ? "aria-required=\"true\"" : string.Empty;
if (property.IsPrimaryKey)
{
@:
@@ -66,7 +67,7 @@
{
@:
@propertyRequiredText
@:
- @:
+ @:
@:
@:
continue;
@@ -77,7 +78,7 @@
{
@:
@propertyRequiredText
@:
@:
}
@@ -85,7 +86,7 @@
{
@:
@propertyRequiredText
@:
- @:
+ @:
@:
@:
}
@@ -93,7 +94,7 @@
{
@:
@propertyRequiredText
@:
- @:
+ @:
@:
@:
}
@@ -101,7 +102,7 @@
{
@:
@propertyRequiredText
@:
- @:
+ @:
@:
@:
}
diff --git a/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/BlazorCrud/Create.cs b/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/BlazorCrud/Create.cs
new file mode 100644
index 000000000..8ed9e7f3b
--- /dev/null
+++ b/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/BlazorCrud/Create.cs
@@ -0,0 +1,473 @@
+// ------------------------------------------------------------------------------
+//
+// 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.
+//
+// ------------------------------------------------------------------------------
+namespace Microsoft.DotNet.Tools.Scaffold.AspNet.Templates.BlazorCrud
+{
+ using System.Collections.Generic;
+ using System.Text;
+ using System.Linq;
+ using Microsoft.DotNet.Tools.Scaffold.AspNet.Extensions;
+ using System;
+
+ ///
+ /// Class to produce the template output
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+ public partial class Create : CreateBase
+ {
+ ///
+ /// Create the template output
+ ///
+ public virtual string TransformText()
+ {
+
+ string modelName = Model.ModelInfo.ModelTypeName;
+ string pluralModel = Model.ModelInfo.ModelTypePluralName;
+ string modelNameLowerInv = modelName.ToLowerInvariant();
+ string pluralModelLowerInv = pluralModel.ToLowerInvariant();
+ string dbContextNamespace = string.IsNullOrEmpty(Model.DbContextInfo.DbContextNamespace) ? string.Empty : Model.DbContextInfo.DbContextNamespace;
+ string dbContextFullName = string.IsNullOrEmpty(dbContextNamespace) ? Model.DbContextInfo.DbContextClassName : $"{dbContextNamespace}.{Model.DbContextInfo.DbContextClassName}";
+ string dbContextFactory = $"IDbContextFactory<{dbContextFullName}> DbFactory";
+ string modelNamespace = Model.ModelInfo.ModelNamespace;
+ var entityProperties = Model.ModelInfo.ModelProperties
+ .Where(x => !x.Name.Equals(Model.ModelInfo.PrimaryKeyName, StringComparison.OrdinalIgnoreCase)).ToList();
+
+ this.Write("@page \"/");
+ this.Write(this.ToStringHelper.ToStringWithCulture(pluralModelLowerInv));
+ this.Write("/create\"\r\n@using Microsoft.EntityFrameworkCore\r\n");
+
+ if (!string.IsNullOrEmpty(modelNamespace))
+ {
+
+ this.Write("@using ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelNamespace));
+ this.Write("\r\n");
+ }
+
+ this.Write("@inject ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(dbContextFactory));
+ this.Write("\r\n@inject NavigationManager NavigationManager\r\n\r\n
Create\r\n\r" +
+ "\n
Create
\r\n\r\n
");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write("
\r\n
\r\n
\r\n
\r\n
\r\n \r\n " +
+ " \r\n ");
+
+ foreach (var property in entityProperties)
+ {
+ string modelPropertyName = property.Name;
+ string modelPropertyNameLowercase = modelPropertyName.ToLowerInvariant();
+ string propertyShortTypeName = property.Type.ToDisplayString().Replace("?", string.Empty);
+ var inputTypeName = Model.GetInputType(propertyShortTypeName);
+ var inputClass = Model.GetInputClassType(propertyShortTypeName);
+ var ariaRequiredAttributeHtml = property.HasRequiredAttribute() ? "aria-required=\"true\"" : string.Empty;
+ var divWhitespace = new string(' ', 16);
+ var requiredSpanAttributeHtml = property.HasRequiredAttribute() ? $"\r\n{divWhitespace}*" : string.Empty;
+
+ this.Write("");
+ this.Write(this.ToStringHelper.ToStringWithCulture(requiredSpanAttributeHtml));
+ this.Write("\r\n \r\n <");
+ this.Write(this.ToStringHelper.ToStringWithCulture(inputTypeName));
+ this.Write(" id=\"");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelPropertyNameLowercase));
+ this.Write("\" @bind-Value=\"");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write(".");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelPropertyName));
+ this.Write("\" class=\"");
+ this.Write(this.ToStringHelper.ToStringWithCulture(inputClass));
+ this.Write("\" ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(ariaRequiredAttributeHtml));
+ this.Write("/> \r\n ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write(".");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelPropertyName));
+ this.Write("\" class=\"text-danger\" /> \r\n
\r\n ");
+ }
+ this.Write("\r\n \r\n
\r\n
\r\n\r\n
\r\n\r\n@code {\r\n [SupplyParameterFromForm]\r\n private" +
+ " ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write(" ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write(" { get; set; } = new();\r\n\r\n // To protect from overposting attacks, see https:" +
+ "//learn.microsoft.com/aspnet/core/blazor/forms/#mitigate-overposting-attacks.\r\n " +
+ " private async Task Add");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write("()\r\n {\r\n using var context = DbFactory.CreateDbContext();\r\n cont" +
+ "ext.");
+ this.Write(this.ToStringHelper.ToStringWithCulture(Model.DbContextInfo.EntitySetVariableName));
+ this.Write(".Add(");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write(");\r\n await context.SaveChangesAsync();\r\n NavigationManager.Navigate" +
+ "To(\"/");
+ this.Write(this.ToStringHelper.ToStringWithCulture(pluralModelLowerInv));
+ this.Write("\");\r\n }\r\n}\r\n");
+ return this.GenerationEnvironment.ToString();
+ }
+ private global::Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost hostValue;
+ ///
+ /// The current host for the text templating engine
+ ///
+ public virtual global::Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost Host
+ {
+ get
+ {
+ return this.hostValue;
+ }
+ set
+ {
+ this.hostValue = value;
+ }
+ }
+
+private global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.BlazorCrudModel _ModelField;
+
+///
+/// Access the Model parameter of the template.
+///
+private global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.BlazorCrudModel Model
+{
+ get
+ {
+ return this._ModelField;
+ }
+}
+
+
+///
+/// Initialize the template
+///
+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.BlazorCrudModel)(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.BlazorCrudModel));
+ if (((tc != null)
+ && tc.CanConvertFrom(typeof(string))))
+ {
+ this._ModelField = ((global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.BlazorCrudModel)(tc.ConvertFrom(parameterValue)));
+ ModelValueAcquired = true;
+ }
+ else
+ {
+ this.Error("The type \'Microsoft.DotNet.Tools.Scaffold.AspNet.Models.BlazorCrudModel\' of the p" +
+ "arameter \'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.BlazorCrudModel)(data));
+ }
+}
+
+
+ }
+}
+
+
+ }
+ #region Base class
+ ///
+ /// Base class for this transformation
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+ public class CreateBase
+ {
+ #region Fields
+ private global::System.Text.StringBuilder generationEnvironmentField;
+ private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField;
+ private global::System.Collections.Generic.List
indentLengthsField;
+ private string currentIndentField = "";
+ private bool endsWithNewline;
+ private global::System.Collections.Generic.IDictionary sessionField;
+ #endregion
+ #region Properties
+ ///
+ /// The string builder that generation-time code is using to assemble generated output
+ ///
+ public System.Text.StringBuilder GenerationEnvironment
+ {
+ get
+ {
+ if ((this.generationEnvironmentField == null))
+ {
+ this.generationEnvironmentField = new global::System.Text.StringBuilder();
+ }
+ return this.generationEnvironmentField;
+ }
+ set
+ {
+ this.generationEnvironmentField = value;
+ }
+ }
+ ///
+ /// The error collection for the generation process
+ ///
+ public System.CodeDom.Compiler.CompilerErrorCollection Errors
+ {
+ get
+ {
+ if ((this.errorsField == null))
+ {
+ this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection();
+ }
+ return this.errorsField;
+ }
+ }
+ ///
+ /// A list of the lengths of each indent that was added with PushIndent
+ ///
+ private System.Collections.Generic.List indentLengths
+ {
+ get
+ {
+ if ((this.indentLengthsField == null))
+ {
+ this.indentLengthsField = new global::System.Collections.Generic.List();
+ }
+ return this.indentLengthsField;
+ }
+ }
+ ///
+ /// Gets the current indent we use when adding lines to the output
+ ///
+ public string CurrentIndent
+ {
+ get
+ {
+ return this.currentIndentField;
+ }
+ }
+ ///
+ /// Current transformation session
+ ///
+ public virtual global::System.Collections.Generic.IDictionary Session
+ {
+ get
+ {
+ return this.sessionField;
+ }
+ set
+ {
+ this.sessionField = value;
+ }
+ }
+ #endregion
+ #region Transform-time helpers
+ ///
+ /// Write text directly into the generated output
+ ///
+ 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);
+ }
+ }
+ ///
+ /// Write text directly into the generated output
+ ///
+ public void WriteLine(string textToAppend)
+ {
+ this.Write(textToAppend);
+ this.GenerationEnvironment.AppendLine();
+ this.endsWithNewline = true;
+ }
+ ///
+ /// Write formatted text directly into the generated output
+ ///
+ public void Write(string format, params object[] args)
+ {
+ this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
+ }
+ ///
+ /// Write formatted text directly into the generated output
+ ///
+ public void WriteLine(string format, params object[] args)
+ {
+ this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
+ }
+ ///
+ /// Raise an error
+ ///
+ public void Error(string message)
+ {
+ System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
+ error.ErrorText = message;
+ this.Errors.Add(error);
+ }
+ ///
+ /// Raise a warning
+ ///
+ 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);
+ }
+ ///
+ /// Increase the indent
+ ///
+ public void PushIndent(string indent)
+ {
+ if ((indent == null))
+ {
+ throw new global::System.ArgumentNullException("indent");
+ }
+ this.currentIndentField = (this.currentIndentField + indent);
+ this.indentLengths.Add(indent.Length);
+ }
+ ///
+ /// Remove the last indent that was added with PushIndent
+ ///
+ 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;
+ }
+ ///
+ /// Remove any indentation
+ ///
+ public void ClearIndent()
+ {
+ this.indentLengths.Clear();
+ this.currentIndentField = "";
+ }
+ #endregion
+ #region ToString Helpers
+ ///
+ /// Utility class to produce culture-oriented representation of an object as a string.
+ ///
+ public class ToStringInstanceHelper
+ {
+ private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture;
+ ///
+ /// Gets or sets format provider to be used by ToStringWithCulture method.
+ ///
+ public System.IFormatProvider FormatProvider
+ {
+ get
+ {
+ return this.formatProviderField ;
+ }
+ set
+ {
+ if ((value != null))
+ {
+ this.formatProviderField = value;
+ }
+ }
+ }
+ ///
+ /// This is called from the compile/run appdomain to convert objects within an expression block to a string
+ ///
+ 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();
+ ///
+ /// Helper to produce culture-oriented representation of an object as a string
+ ///
+ public ToStringInstanceHelper ToStringHelper
+ {
+ get
+ {
+ return this.toStringHelperField;
+ }
+ }
+ #endregion
+ }
+ #endregion
+}
diff --git a/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/BlazorCrud/Create.tt b/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/BlazorCrud/Create.tt
new file mode 100644
index 000000000..ce0755347
--- /dev/null
+++ b/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/BlazorCrud/Create.tt
@@ -0,0 +1,80 @@
+<#@ template hostSpecific="true" linePragmas="false" #>
+<#@ parameter type="Microsoft.DotNet.Tools.Scaffold.AspNet.Models.BlazorCrudModel" name="Model" #>
+<#@ import namespace="System.Collections.Generic" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Linq" #>
+<#@ import namespace="Microsoft.DotNet.Tools.Scaffold.AspNet.Extensions" #>
+<#
+ string modelName = Model.ModelInfo.ModelTypeName;
+ string pluralModel = Model.ModelInfo.ModelTypePluralName;
+ string modelNameLowerInv = modelName.ToLowerInvariant();
+ string pluralModelLowerInv = pluralModel.ToLowerInvariant();
+ string dbContextNamespace = string.IsNullOrEmpty(Model.DbContextInfo.DbContextNamespace) ? string.Empty : Model.DbContextInfo.DbContextNamespace;
+ string dbContextFullName = string.IsNullOrEmpty(dbContextNamespace) ? Model.DbContextInfo.DbContextClassName : $"{dbContextNamespace}.{Model.DbContextInfo.DbContextClassName}";
+ string dbContextFactory = $"IDbContextFactory<{dbContextFullName}> DbFactory";
+ string modelNamespace = Model.ModelInfo.ModelNamespace;
+ var entityProperties = Model.ModelInfo.ModelProperties
+ .Where(x => !x.Name.Equals(Model.ModelInfo.PrimaryKeyName, StringComparison.OrdinalIgnoreCase)).ToList();
+#>
+@page "/<#= pluralModelLowerInv #>/create"
+@using Microsoft.EntityFrameworkCore
+<#
+ if (!string.IsNullOrEmpty(modelNamespace))
+ {
+ #>@using <#= modelNamespace#>
+<# }
+#>
+@inject <#=dbContextFactory #>
+@inject NavigationManager NavigationManager
+
+Create
+
+Create
+
+<#= modelName #>
+
+
+
+
+
+
+ <#
+ foreach (var property in entityProperties)
+ {
+ string modelPropertyName = property.Name;
+ string modelPropertyNameLowercase = modelPropertyName.ToLowerInvariant();
+ string propertyShortTypeName = property.Type.ToDisplayString().Replace("?", string.Empty);
+ var inputTypeName = Model.GetInputType(propertyShortTypeName);
+ var inputClass = Model.GetInputClassType(propertyShortTypeName);
+ var ariaRequiredAttributeHtml = property.HasRequiredAttribute() ? "aria-required=\"true\"" : string.Empty;
+ var divWhitespace = new string(' ', 16);
+ var requiredSpanAttributeHtml = property.HasRequiredAttribute() ? $"\r\n{divWhitespace}*" : string.Empty;
+ #>
+<#= requiredSpanAttributeHtml #>
+
+ <<#= inputTypeName #> id="<#= modelPropertyNameLowercase #>" @bind-Value="<#= modelName #>.<#= modelPropertyName #>" class="<#= inputClass #>" <#= ariaRequiredAttributeHtml #>/>
+
+
+ <# } #>
+
+
+
+
+
+
+
+@code {
+ [SupplyParameterFromForm]
+ private <#= modelName #> <#= modelName #> { get; set; } = new();
+
+ // To protect from overposting attacks, see https://learn.microsoft.com/aspnet/core/blazor/forms/#mitigate-overposting-attacks.
+ private async Task Add<#= modelName #>()
+ {
+ using var context = DbFactory.CreateDbContext();
+ context.<#= Model.DbContextInfo.EntitySetVariableName #>.Add(<#= modelName #>);
+ await context.SaveChangesAsync();
+ NavigationManager.NavigateTo("/<#= pluralModelLowerInv #>");
+ }
+}
diff --git a/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/BlazorCrud/Edit.cs b/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/BlazorCrud/Edit.cs
new file mode 100644
index 000000000..dcd6a8c5c
--- /dev/null
+++ b/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/BlazorCrud/Edit.cs
@@ -0,0 +1,529 @@
+// ------------------------------------------------------------------------------
+//
+// 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.
+//
+// ------------------------------------------------------------------------------
+namespace Microsoft.DotNet.Tools.Scaffold.AspNet.Templates.BlazorCrud
+{
+ using System.Collections.Generic;
+ using System.Text;
+ using System.Linq;
+ using Microsoft.DotNet.Tools.Scaffold.AspNet.Extensions;
+ using System;
+
+ ///
+ /// Class to produce the template output
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+ public partial class Edit : EditBase
+ {
+ ///
+ /// Create the template output
+ ///
+ public virtual string TransformText()
+ {
+
+ string modelName = Model.ModelInfo.ModelTypeName;
+ string pluralModel = Model.ModelInfo.ModelTypePluralName;
+ string modelNameLowerInv = modelName.ToLowerInvariant();
+ string pluralModelLowerInv = pluralModel.ToLowerInvariant();
+ string dbContextNamespace = string.IsNullOrEmpty(Model.DbContextInfo.DbContextNamespace) ? string.Empty : Model.DbContextInfo.DbContextNamespace;
+ string dbContextFullName = string.IsNullOrEmpty(dbContextNamespace) ? Model.DbContextInfo.DbContextClassName : $"{dbContextNamespace}.{Model.DbContextInfo.DbContextClassName}";
+ string dbContextFactory = $"IDbContextFactory<{dbContextFullName}> DbFactory";
+ string modelNamespace = Model.ModelInfo.ModelNamespace;
+ var entityProperties = Model.ModelInfo.ModelProperties
+ .Where(x => !x.Name.Equals(Model.ModelInfo.PrimaryKeyName, StringComparison.OrdinalIgnoreCase)).ToList();
+ string primaryKeyName = Model.ModelInfo.PrimaryKeyName;
+ string primaryKeyNameLowerInv = primaryKeyName.ToLowerInvariant();
+ string primaryKeyShortTypeName = Model.ModelInfo.PrimaryKeyTypeName;
+ string entitySetName = Model.DbContextInfo.EntitySetVariableName;
+
+ this.Write("@page \"/");
+ this.Write(this.ToStringHelper.ToStringWithCulture(pluralModelLowerInv));
+ this.Write("/edit\"\r\n@using Microsoft.EntityFrameworkCore\r\n");
+
+ if (!string.IsNullOrEmpty(modelNamespace))
+ {
+
+ this.Write("@using ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelNamespace));
+ this.Write("\r\n");
+ }
+
+ this.Write("@inject ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(dbContextFactory));
+ this.Write("\r\n@inject NavigationManager NavigationManager\r\n\r\nEdit\r\n\r\n<" +
+ "h1>Edit\r\n\r\n");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write("
\r\n
\r\n@if (");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write(" is null)\r\n{\r\n Loading...
\r\n}\r\nelse\r\n{\r\n \r\n" +
+ "
\r\n
\r\n \r\n " +
+ " \r\n \r\n");
+
+ foreach (var property in entityProperties)
+ {
+ string modelPropertyName = property.Name;
+ string modelPropertyNameLowercase = modelPropertyName.ToLowerInvariant();
+ string propertyShortTypeName = property.Type.ToDisplayString().Replace("?", string.Empty);
+ var inputTypeName = Model.GetInputType(propertyShortTypeName);
+ var inputClass = Model.GetInputClassType(propertyShortTypeName);
+ var ariaRequiredAttributeHtml = property.HasRequiredAttribute() ? "aria-required=\"true\"" : string.Empty;
+ var divWhitespace = new string(' ', 16);
+ var requiredSpanAttributeHtml = property.HasRequiredAttribute() ? $"\r\n{divWhitespace}*" : string.Empty;
+
+ this.Write(" ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(requiredSpanAttributeHtml));
+ this.Write("\r\n \r\n <");
+ this.Write(this.ToStringHelper.ToStringWithCulture(inputTypeName));
+ this.Write(" id=\"");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelPropertyNameLowercase));
+ this.Write("\" @bind-Value=\"");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write(".");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelPropertyName));
+ this.Write("\" class=\"");
+ this.Write(this.ToStringHelper.ToStringWithCulture(inputClass));
+ this.Write("\" ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(ariaRequiredAttributeHtml));
+ this.Write("/>\r\n ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write(".");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelPropertyName));
+ this.Write("\" class=\"text-danger\" />\r\n
\r\n");
+ }
+ this.Write(" \r\n " +
+ " \r\n
\r\n
\r\n}\r\n\r\n\r\n\r\n@code {\r\n [SupplyParameterFromQuery]\r\n privat" +
+ "e ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(primaryKeyShortTypeName));
+ this.Write(" ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(primaryKeyName));
+ this.Write(" { get; set; }\r\n\r\n [SupplyParameterFromForm]\r\n private ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write("? ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write(" { get; set; }\r\n\r\n protected override async Task OnInitializedAsync()\r\n {\r\n" +
+ " using var context = DbFactory.CreateDbContext();\r\n ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write(" ??= await context.");
+ this.Write(this.ToStringHelper.ToStringWithCulture(entitySetName));
+ this.Write(".FirstOrDefaultAsync(m => m.");
+ this.Write(this.ToStringHelper.ToStringWithCulture(primaryKeyName));
+ this.Write(" == ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(primaryKeyName));
+ this.Write(");\r\n\r\n if (");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write(@" is null)
+ {
+ NavigationManager.NavigateTo(""notfound"");
+ }
+ }
+
+ // To protect from overposting attacks, enable the specific properties you want to bind to.
+ // For more information, see https://learn.microsoft.com/aspnet/core/blazor/forms/#mitigate-overposting-attacks.
+ private async Task Update");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write("()\r\n {\r\n using var context = DbFactory.CreateDbContext();\r\n cont" +
+ "ext.Attach(");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ 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(");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write("!.");
+ this.Write(this.ToStringHelper.ToStringWithCulture(primaryKeyName));
+ this.Write("))\r\n {\r\n NavigationManager.NavigateTo(\"notfound\");\r\n " +
+ " }\r\n else\r\n {\r\n throw;\r\n " +
+ " }\r\n }\r\n\r\n NavigationManager.NavigateTo(\"/");
+ this.Write(this.ToStringHelper.ToStringWithCulture(pluralModelLowerInv));
+ this.Write("\");\r\n }\r\n\r\n private bool ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write("Exists(");
+ this.Write(this.ToStringHelper.ToStringWithCulture(primaryKeyShortTypeName));
+ this.Write(" ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(primaryKeyNameLowerInv));
+ this.Write(")\r\n {\r\n using var context = DbFactory.CreateDbContext();\r\n retur" +
+ "n context.");
+ this.Write(this.ToStringHelper.ToStringWithCulture(entitySetName));
+ this.Write(".Any(e => e.");
+ this.Write(this.ToStringHelper.ToStringWithCulture(primaryKeyName));
+ this.Write(" == ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(primaryKeyNameLowerInv));
+ this.Write(");\r\n }\r\n}\r\n");
+ return this.GenerationEnvironment.ToString();
+ }
+ private global::Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost hostValue;
+ ///
+ /// The current host for the text templating engine
+ ///
+ public virtual global::Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost Host
+ {
+ get
+ {
+ return this.hostValue;
+ }
+ set
+ {
+ this.hostValue = value;
+ }
+ }
+
+private global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.BlazorCrudModel _ModelField;
+
+///
+/// Access the Model parameter of the template.
+///
+private global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.BlazorCrudModel Model
+{
+ get
+ {
+ return this._ModelField;
+ }
+}
+
+
+///
+/// Initialize the template
+///
+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.BlazorCrudModel)(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.BlazorCrudModel));
+ if (((tc != null)
+ && tc.CanConvertFrom(typeof(string))))
+ {
+ this._ModelField = ((global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.BlazorCrudModel)(tc.ConvertFrom(parameterValue)));
+ ModelValueAcquired = true;
+ }
+ else
+ {
+ this.Error("The type \'Microsoft.DotNet.Tools.Scaffold.AspNet.Models.BlazorCrudModel\' of the p" +
+ "arameter \'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.BlazorCrudModel)(data));
+ }
+}
+
+
+ }
+}
+
+
+ }
+ #region Base class
+ ///
+ /// Base class for this transformation
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+ public class EditBase
+ {
+ #region Fields
+ private global::System.Text.StringBuilder generationEnvironmentField;
+ private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField;
+ private global::System.Collections.Generic.List indentLengthsField;
+ private string currentIndentField = "";
+ private bool endsWithNewline;
+ private global::System.Collections.Generic.IDictionary sessionField;
+ #endregion
+ #region Properties
+ ///
+ /// The string builder that generation-time code is using to assemble generated output
+ ///
+ public System.Text.StringBuilder GenerationEnvironment
+ {
+ get
+ {
+ if ((this.generationEnvironmentField == null))
+ {
+ this.generationEnvironmentField = new global::System.Text.StringBuilder();
+ }
+ return this.generationEnvironmentField;
+ }
+ set
+ {
+ this.generationEnvironmentField = value;
+ }
+ }
+ ///
+ /// The error collection for the generation process
+ ///
+ public System.CodeDom.Compiler.CompilerErrorCollection Errors
+ {
+ get
+ {
+ if ((this.errorsField == null))
+ {
+ this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection();
+ }
+ return this.errorsField;
+ }
+ }
+ ///
+ /// A list of the lengths of each indent that was added with PushIndent
+ ///
+ private System.Collections.Generic.List indentLengths
+ {
+ get
+ {
+ if ((this.indentLengthsField == null))
+ {
+ this.indentLengthsField = new global::System.Collections.Generic.List();
+ }
+ return this.indentLengthsField;
+ }
+ }
+ ///
+ /// Gets the current indent we use when adding lines to the output
+ ///
+ public string CurrentIndent
+ {
+ get
+ {
+ return this.currentIndentField;
+ }
+ }
+ ///
+ /// Current transformation session
+ ///
+ public virtual global::System.Collections.Generic.IDictionary Session
+ {
+ get
+ {
+ return this.sessionField;
+ }
+ set
+ {
+ this.sessionField = value;
+ }
+ }
+ #endregion
+ #region Transform-time helpers
+ ///
+ /// Write text directly into the generated output
+ ///
+ 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);
+ }
+ }
+ ///
+ /// Write text directly into the generated output
+ ///
+ public void WriteLine(string textToAppend)
+ {
+ this.Write(textToAppend);
+ this.GenerationEnvironment.AppendLine();
+ this.endsWithNewline = true;
+ }
+ ///
+ /// Write formatted text directly into the generated output
+ ///
+ public void Write(string format, params object[] args)
+ {
+ this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
+ }
+ ///
+ /// Write formatted text directly into the generated output
+ ///
+ public void WriteLine(string format, params object[] args)
+ {
+ this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
+ }
+ ///
+ /// Raise an error
+ ///
+ public void Error(string message)
+ {
+ System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
+ error.ErrorText = message;
+ this.Errors.Add(error);
+ }
+ ///
+ /// Raise a warning
+ ///
+ 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);
+ }
+ ///
+ /// Increase the indent
+ ///
+ public void PushIndent(string indent)
+ {
+ if ((indent == null))
+ {
+ throw new global::System.ArgumentNullException("indent");
+ }
+ this.currentIndentField = (this.currentIndentField + indent);
+ this.indentLengths.Add(indent.Length);
+ }
+ ///
+ /// Remove the last indent that was added with PushIndent
+ ///
+ 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;
+ }
+ ///
+ /// Remove any indentation
+ ///
+ public void ClearIndent()
+ {
+ this.indentLengths.Clear();
+ this.currentIndentField = "";
+ }
+ #endregion
+ #region ToString Helpers
+ ///
+ /// Utility class to produce culture-oriented representation of an object as a string.
+ ///
+ public class ToStringInstanceHelper
+ {
+ private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture;
+ ///
+ /// Gets or sets format provider to be used by ToStringWithCulture method.
+ ///
+ public System.IFormatProvider FormatProvider
+ {
+ get
+ {
+ return this.formatProviderField ;
+ }
+ set
+ {
+ if ((value != null))
+ {
+ this.formatProviderField = value;
+ }
+ }
+ }
+ ///
+ /// This is called from the compile/run appdomain to convert objects within an expression block to a string
+ ///
+ 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();
+ ///
+ /// Helper to produce culture-oriented representation of an object as a string
+ ///
+ public ToStringInstanceHelper ToStringHelper
+ {
+ get
+ {
+ return this.toStringHelperField;
+ }
+ }
+ #endregion
+ }
+ #endregion
+}
diff --git a/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/BlazorCrud/Edit.tt b/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/BlazorCrud/Edit.tt
new file mode 100644
index 000000000..406d7cb44
--- /dev/null
+++ b/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/BlazorCrud/Edit.tt
@@ -0,0 +1,129 @@
+<#@ template hostSpecific="true" linePragmas="false" #>
+<#@ parameter type="Microsoft.DotNet.Tools.Scaffold.AspNet.Models.BlazorCrudModel" name="Model" #>
+<#@ import namespace="System.Collections.Generic" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Linq" #>
+<#@ import namespace="Microsoft.DotNet.Tools.Scaffold.AspNet.Extensions" #>
+<#
+ string modelName = Model.ModelInfo.ModelTypeName;
+ string pluralModel = Model.ModelInfo.ModelTypePluralName;
+ string modelNameLowerInv = modelName.ToLowerInvariant();
+ string pluralModelLowerInv = pluralModel.ToLowerInvariant();
+ string dbContextNamespace = string.IsNullOrEmpty(Model.DbContextInfo.DbContextNamespace) ? string.Empty : Model.DbContextInfo.DbContextNamespace;
+ string dbContextFullName = string.IsNullOrEmpty(dbContextNamespace) ? Model.DbContextInfo.DbContextClassName : $"{dbContextNamespace}.{Model.DbContextInfo.DbContextClassName}";
+ string dbContextFactory = $"IDbContextFactory<{dbContextFullName}> DbFactory";
+ string modelNamespace = Model.ModelInfo.ModelNamespace;
+ var entityProperties = Model.ModelInfo.ModelProperties
+ .Where(x => !x.Name.Equals(Model.ModelInfo.PrimaryKeyName, StringComparison.OrdinalIgnoreCase)).ToList();
+ string primaryKeyName = Model.ModelInfo.PrimaryKeyName;
+ string primaryKeyNameLowerInv = primaryKeyName.ToLowerInvariant();
+ string primaryKeyShortTypeName = Model.ModelInfo.PrimaryKeyTypeName;
+ string entitySetName = Model.DbContextInfo.EntitySetVariableName;
+#>
+@page "/<#= pluralModelLowerInv #>/edit"
+@using Microsoft.EntityFrameworkCore
+<#
+ if (!string.IsNullOrEmpty(modelNamespace))
+ {
+ #>@using <#= modelNamespace#>
+<# }
+#>
+@inject <#=dbContextFactory #>
+@inject NavigationManager NavigationManager
+
+Edit
+
+Edit
+
+<#= modelName #>
+
+@if (<#= modelName #> is null)
+{
+ Loading...
+}
+else
+{
+
+
+
+
+
+
+<#
+ foreach (var property in entityProperties)
+ {
+ string modelPropertyName = property.Name;
+ string modelPropertyNameLowercase = modelPropertyName.ToLowerInvariant();
+ string propertyShortTypeName = property.Type.ToDisplayString().Replace("?", string.Empty);
+ var inputTypeName = Model.GetInputType(propertyShortTypeName);
+ var inputClass = Model.GetInputClassType(propertyShortTypeName);
+ var ariaRequiredAttributeHtml = property.HasRequiredAttribute() ? "aria-required=\"true\"" : string.Empty;
+ var divWhitespace = new string(' ', 16);
+ var requiredSpanAttributeHtml = property.HasRequiredAttribute() ? $"\r\n{divWhitespace}*" : string.Empty;
+#>
+ <#= requiredSpanAttributeHtml #>
+
+ <<#= inputTypeName #> id="<#= modelPropertyNameLowercase #>" @bind-Value="<#= modelName #>.<#= modelPropertyName #>" class="<#= inputClass #>" <#= ariaRequiredAttributeHtml #>/>
+
+
+<# } #>
+
+
+
+
+}
+
+
+
+@code {
+ [SupplyParameterFromQuery]
+ private <#= primaryKeyShortTypeName #> <#= primaryKeyName #> { get; set; }
+
+ [SupplyParameterFromForm]
+ private <#= modelName #>? <#= modelName #> { get; set; }
+
+ protected override async Task OnInitializedAsync()
+ {
+ using var context = DbFactory.CreateDbContext();
+ <#= modelName #> ??= await context.<#= entitySetName #>.FirstOrDefaultAsync(m => m.<#= primaryKeyName #> == <#= primaryKeyName #>);
+
+ if (<#= modelName #> is null)
+ {
+ NavigationManager.NavigateTo("notfound");
+ }
+ }
+
+ // To protect from overposting attacks, enable the specific properties you want to bind to.
+ // For more information, see https://learn.microsoft.com/aspnet/core/blazor/forms/#mitigate-overposting-attacks.
+ private async Task Update<#= modelName #>()
+ {
+ using var context = DbFactory.CreateDbContext();
+ context.Attach(<#= modelName #>!).State = EntityState.Modified;
+
+ try
+ {
+ await context.SaveChangesAsync();
+ }
+ catch (DbUpdateConcurrencyException)
+ {
+ if (!<#= modelName #>Exists(<#= modelName #>!.<#= primaryKeyName #>))
+ {
+ NavigationManager.NavigateTo("notfound");
+ }
+ else
+ {
+ throw;
+ }
+ }
+
+ NavigationManager.NavigateTo("/<#= pluralModelLowerInv #>");
+ }
+
+ private bool <#= modelName #>Exists(<#= primaryKeyShortTypeName #> <#= primaryKeyNameLowerInv #>)
+ {
+ using var context = DbFactory.CreateDbContext();
+ return context.<#= entitySetName #>.Any(e => e.<#= primaryKeyName #> == <#= primaryKeyNameLowerInv #>);
+ }
+}
diff --git a/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/RazorPages/Create.cs b/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/RazorPages/Create.cs
new file mode 100644
index 000000000..7108a1965
--- /dev/null
+++ b/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/RazorPages/Create.cs
@@ -0,0 +1,447 @@
+// ------------------------------------------------------------------------------
+//
+// 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.
+//
+// ------------------------------------------------------------------------------
+namespace Microsoft.DotNet.Tools.Scaffold.AspNet.Templates.RazorPages
+{
+ using System.Collections.Generic;
+ using System.Text;
+ using System.Linq;
+ using Microsoft.DotNet.Tools.Scaffold.AspNet.Extensions;
+ using System;
+
+ ///
+ /// Class to produce the template output
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+ public partial class Create : CreateBase
+ {
+ ///
+ /// Create the template output
+ ///
+ public virtual string TransformText()
+ {
+
+ string modelName = Model.ModelInfo.ModelTypeName;
+ string modelNameLowerVariant = modelName.ToLowerInvariant();
+ string modelNamespace = Model.ModelInfo.ModelNamespace;
+ string modelFullName = string.IsNullOrEmpty(modelNamespace) ? modelName : $"{modelNamespace}.{modelName}";
+
+ var entityProperties = Model.ModelInfo.ModelProperties
+ .Where(x => !x.Name.Equals(Model.ModelInfo.PrimaryKeyName, StringComparison.OrdinalIgnoreCase)).ToList();
+ string pageModelFullName = string.IsNullOrEmpty(Model.RazorPageNamespace) ? "CreateModel" : $"{Model.RazorPageNamespace}.CreateModel";
+
+ this.Write("@page\r\n@model ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(pageModelFullName));
+ this.Write("\r\n\r\n@{\r\n ViewData[\"Title\"] = \"Create\";\r\n}\r\n\r\nCreate
\r\n\r\n");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write("
\r\n
\r\n
+
+
+
+@section Scripts {
+ @{await Html.RenderPartialAsync(""_ValidationScriptsPartial"");}
+}
+");
+ return this.GenerationEnvironment.ToString();
+ }
+ private global::Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost hostValue;
+ ///
+ /// The current host for the text templating engine
+ ///
+ public virtual global::Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost Host
+ {
+ get
+ {
+ return this.hostValue;
+ }
+ set
+ {
+ this.hostValue = value;
+ }
+ }
+
+private global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.RazorPageModel _ModelField;
+
+///
+/// Access the Model parameter of the template.
+///
+private global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.RazorPageModel Model
+{
+ get
+ {
+ return this._ModelField;
+ }
+}
+
+
+///
+/// Initialize the template
+///
+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.RazorPageModel)(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.RazorPageModel));
+ if (((tc != null)
+ && tc.CanConvertFrom(typeof(string))))
+ {
+ this._ModelField = ((global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.RazorPageModel)(tc.ConvertFrom(parameterValue)));
+ ModelValueAcquired = true;
+ }
+ else
+ {
+ this.Error("The type \'Microsoft.DotNet.Tools.Scaffold.AspNet.Models.RazorPageModel\' of the pa" +
+ "rameter \'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.RazorPageModel)(data));
+ }
+}
+
+
+ }
+}
+
+
+ }
+ #region Base class
+ ///
+ /// Base class for this transformation
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+ public class CreateBase
+ {
+ #region Fields
+ private global::System.Text.StringBuilder generationEnvironmentField;
+ private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField;
+ private global::System.Collections.Generic.List indentLengthsField;
+ private string currentIndentField = "";
+ private bool endsWithNewline;
+ private global::System.Collections.Generic.IDictionary sessionField;
+ #endregion
+ #region Properties
+ ///
+ /// The string builder that generation-time code is using to assemble generated output
+ ///
+ public System.Text.StringBuilder GenerationEnvironment
+ {
+ get
+ {
+ if ((this.generationEnvironmentField == null))
+ {
+ this.generationEnvironmentField = new global::System.Text.StringBuilder();
+ }
+ return this.generationEnvironmentField;
+ }
+ set
+ {
+ this.generationEnvironmentField = value;
+ }
+ }
+ ///
+ /// The error collection for the generation process
+ ///
+ public System.CodeDom.Compiler.CompilerErrorCollection Errors
+ {
+ get
+ {
+ if ((this.errorsField == null))
+ {
+ this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection();
+ }
+ return this.errorsField;
+ }
+ }
+ ///
+ /// A list of the lengths of each indent that was added with PushIndent
+ ///
+ private System.Collections.Generic.List indentLengths
+ {
+ get
+ {
+ if ((this.indentLengthsField == null))
+ {
+ this.indentLengthsField = new global::System.Collections.Generic.List();
+ }
+ return this.indentLengthsField;
+ }
+ }
+ ///
+ /// Gets the current indent we use when adding lines to the output
+ ///
+ public string CurrentIndent
+ {
+ get
+ {
+ return this.currentIndentField;
+ }
+ }
+ ///
+ /// Current transformation session
+ ///
+ public virtual global::System.Collections.Generic.IDictionary Session
+ {
+ get
+ {
+ return this.sessionField;
+ }
+ set
+ {
+ this.sessionField = value;
+ }
+ }
+ #endregion
+ #region Transform-time helpers
+ ///
+ /// Write text directly into the generated output
+ ///
+ 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);
+ }
+ }
+ ///
+ /// Write text directly into the generated output
+ ///
+ public void WriteLine(string textToAppend)
+ {
+ this.Write(textToAppend);
+ this.GenerationEnvironment.AppendLine();
+ this.endsWithNewline = true;
+ }
+ ///
+ /// Write formatted text directly into the generated output
+ ///
+ public void Write(string format, params object[] args)
+ {
+ this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
+ }
+ ///
+ /// Write formatted text directly into the generated output
+ ///
+ public void WriteLine(string format, params object[] args)
+ {
+ this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
+ }
+ ///
+ /// Raise an error
+ ///
+ public void Error(string message)
+ {
+ System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
+ error.ErrorText = message;
+ this.Errors.Add(error);
+ }
+ ///
+ /// Raise a warning
+ ///
+ 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);
+ }
+ ///
+ /// Increase the indent
+ ///
+ public void PushIndent(string indent)
+ {
+ if ((indent == null))
+ {
+ throw new global::System.ArgumentNullException("indent");
+ }
+ this.currentIndentField = (this.currentIndentField + indent);
+ this.indentLengths.Add(indent.Length);
+ }
+ ///
+ /// Remove the last indent that was added with PushIndent
+ ///
+ 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;
+ }
+ ///
+ /// Remove any indentation
+ ///
+ public void ClearIndent()
+ {
+ this.indentLengths.Clear();
+ this.currentIndentField = "";
+ }
+ #endregion
+ #region ToString Helpers
+ ///
+ /// Utility class to produce culture-oriented representation of an object as a string.
+ ///
+ public class ToStringInstanceHelper
+ {
+ private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture;
+ ///
+ /// Gets or sets format provider to be used by ToStringWithCulture method.
+ ///
+ public System.IFormatProvider FormatProvider
+ {
+ get
+ {
+ return this.formatProviderField ;
+ }
+ set
+ {
+ if ((value != null))
+ {
+ this.formatProviderField = value;
+ }
+ }
+ }
+ ///
+ /// This is called from the compile/run appdomain to convert objects within an expression block to a string
+ ///
+ 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();
+ ///
+ /// Helper to produce culture-oriented representation of an object as a string
+ ///
+ public ToStringInstanceHelper ToStringHelper
+ {
+ get
+ {
+ return this.toStringHelperField;
+ }
+ }
+ #endregion
+ }
+ #endregion
+}
diff --git a/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/RazorPages/Create.tt b/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/RazorPages/Create.tt
new file mode 100644
index 000000000..6a7c6150c
--- /dev/null
+++ b/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/RazorPages/Create.tt
@@ -0,0 +1,64 @@
+<#@ template hostSpecific="true" linePragmas="false" #>
+<#@ parameter type="Microsoft.DotNet.Tools.Scaffold.AspNet.Models.RazorPageModel" name="Model" #>
+<#@ import namespace="System.Collections.Generic" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Linq" #>
+<#@ import namespace="Microsoft.DotNet.Tools.Scaffold.AspNet.Extensions" #>
+<#
+ string modelName = Model.ModelInfo.ModelTypeName;
+ string modelNameLowerVariant = modelName.ToLowerInvariant();
+ string modelNamespace = Model.ModelInfo.ModelNamespace;
+ string modelFullName = string.IsNullOrEmpty(modelNamespace) ? modelName : $"{modelNamespace}.{modelName}";
+
+ var entityProperties = Model.ModelInfo.ModelProperties
+ .Where(x => !x.Name.Equals(Model.ModelInfo.PrimaryKeyName, StringComparison.OrdinalIgnoreCase)).ToList();
+ string pageModelFullName = string.IsNullOrEmpty(Model.RazorPageNamespace) ? "CreateModel" : $"{Model.RazorPageNamespace}.CreateModel";
+#>
+@page
+@model <#= pageModelFullName #>
+
+@{
+ ViewData["Title"] = "Create";
+}
+
+Create
+
+<#= modelName #>
+
+
+
+
+
+@section Scripts {
+ @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
+}
diff --git a/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/RazorPages/Edit.cs b/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/RazorPages/Edit.cs
new file mode 100644
index 000000000..c97339060
--- /dev/null
+++ b/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/RazorPages/Edit.cs
@@ -0,0 +1,451 @@
+// ------------------------------------------------------------------------------
+//
+// 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.
+//
+// ------------------------------------------------------------------------------
+namespace Microsoft.DotNet.Tools.Scaffold.AspNet.Templates.RazorPages
+{
+ using System.Collections.Generic;
+ using System.Text;
+ using System.Linq;
+ using Microsoft.DotNet.Tools.Scaffold.AspNet.Extensions;
+ using System;
+
+ ///
+ /// Class to produce the template output
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+ public partial class Edit : EditBase
+ {
+ ///
+ /// Create the template output
+ ///
+ public virtual string TransformText()
+ {
+
+ string modelName = Model.ModelInfo.ModelTypeName;
+ string modelNamespace = Model.ModelInfo.ModelNamespace;
+ string modelNameCapitalized = Model.ModelInfo.ModelTypeNameCapitalized;
+ string modelFullName = string.IsNullOrEmpty(modelNamespace) ? modelName : $"{modelNamespace}.{modelName}";
+ var entityProperties = Model.ModelInfo.ModelProperties
+ .Where(x => !x.Name.Equals(Model.ModelInfo.PrimaryKeyName, StringComparison.OrdinalIgnoreCase)).ToList();
+ string primaryKeyName = Model.ModelInfo.PrimaryKeyName;
+ string pageModelFullName = string.IsNullOrEmpty(Model.RazorPageNamespace) ? "EditModel" : $"{Model.RazorPageNamespace}.EditModel";
+
+ this.Write("@page\r\n@model ");
+ this.Write(this.ToStringHelper.ToStringWithCulture(pageModelFullName));
+ this.Write("\r\n\r\n@{\r\n ViewData[\"Title\"] = \"Edit\";\r\n}\r\n\r\nEdit
\r\n\r\n");
+ this.Write(this.ToStringHelper.ToStringWithCulture(modelName));
+ this.Write("
\r\n
\r\n
+
+
+
+@section Scripts {
+ @{await Html.RenderPartialAsync(""_ValidationScriptsPartial"");}
+}
+");
+ return this.GenerationEnvironment.ToString();
+ }
+ private global::Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost hostValue;
+ ///
+ /// The current host for the text templating engine
+ ///
+ public virtual global::Microsoft.VisualStudio.TextTemplating.ITextTemplatingEngineHost Host
+ {
+ get
+ {
+ return this.hostValue;
+ }
+ set
+ {
+ this.hostValue = value;
+ }
+ }
+
+private global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.RazorPageModel _ModelField;
+
+///
+/// Access the Model parameter of the template.
+///
+private global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.RazorPageModel Model
+{
+ get
+ {
+ return this._ModelField;
+ }
+}
+
+
+///
+/// Initialize the template
+///
+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.RazorPageModel)(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.RazorPageModel));
+ if (((tc != null)
+ && tc.CanConvertFrom(typeof(string))))
+ {
+ this._ModelField = ((global::Microsoft.DotNet.Tools.Scaffold.AspNet.Models.RazorPageModel)(tc.ConvertFrom(parameterValue)));
+ ModelValueAcquired = true;
+ }
+ else
+ {
+ this.Error("The type \'Microsoft.DotNet.Tools.Scaffold.AspNet.Models.RazorPageModel\' of the pa" +
+ "rameter \'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.RazorPageModel)(data));
+ }
+}
+
+
+ }
+}
+
+
+ }
+ #region Base class
+ ///
+ /// Base class for this transformation
+ ///
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "17.0.0.0")]
+ public class EditBase
+ {
+ #region Fields
+ private global::System.Text.StringBuilder generationEnvironmentField;
+ private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField;
+ private global::System.Collections.Generic.List indentLengthsField;
+ private string currentIndentField = "";
+ private bool endsWithNewline;
+ private global::System.Collections.Generic.IDictionary sessionField;
+ #endregion
+ #region Properties
+ ///
+ /// The string builder that generation-time code is using to assemble generated output
+ ///
+ public System.Text.StringBuilder GenerationEnvironment
+ {
+ get
+ {
+ if ((this.generationEnvironmentField == null))
+ {
+ this.generationEnvironmentField = new global::System.Text.StringBuilder();
+ }
+ return this.generationEnvironmentField;
+ }
+ set
+ {
+ this.generationEnvironmentField = value;
+ }
+ }
+ ///
+ /// The error collection for the generation process
+ ///
+ public System.CodeDom.Compiler.CompilerErrorCollection Errors
+ {
+ get
+ {
+ if ((this.errorsField == null))
+ {
+ this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection();
+ }
+ return this.errorsField;
+ }
+ }
+ ///
+ /// A list of the lengths of each indent that was added with PushIndent
+ ///
+ private System.Collections.Generic.List indentLengths
+ {
+ get
+ {
+ if ((this.indentLengthsField == null))
+ {
+ this.indentLengthsField = new global::System.Collections.Generic.List();
+ }
+ return this.indentLengthsField;
+ }
+ }
+ ///
+ /// Gets the current indent we use when adding lines to the output
+ ///
+ public string CurrentIndent
+ {
+ get
+ {
+ return this.currentIndentField;
+ }
+ }
+ ///
+ /// Current transformation session
+ ///
+ public virtual global::System.Collections.Generic.IDictionary Session
+ {
+ get
+ {
+ return this.sessionField;
+ }
+ set
+ {
+ this.sessionField = value;
+ }
+ }
+ #endregion
+ #region Transform-time helpers
+ ///
+ /// Write text directly into the generated output
+ ///
+ 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);
+ }
+ }
+ ///
+ /// Write text directly into the generated output
+ ///
+ public void WriteLine(string textToAppend)
+ {
+ this.Write(textToAppend);
+ this.GenerationEnvironment.AppendLine();
+ this.endsWithNewline = true;
+ }
+ ///
+ /// Write formatted text directly into the generated output
+ ///
+ public void Write(string format, params object[] args)
+ {
+ this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
+ }
+ ///
+ /// Write formatted text directly into the generated output
+ ///
+ public void WriteLine(string format, params object[] args)
+ {
+ this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
+ }
+ ///
+ /// Raise an error
+ ///
+ public void Error(string message)
+ {
+ System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
+ error.ErrorText = message;
+ this.Errors.Add(error);
+ }
+ ///
+ /// Raise a warning
+ ///
+ 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);
+ }
+ ///
+ /// Increase the indent
+ ///
+ public void PushIndent(string indent)
+ {
+ if ((indent == null))
+ {
+ throw new global::System.ArgumentNullException("indent");
+ }
+ this.currentIndentField = (this.currentIndentField + indent);
+ this.indentLengths.Add(indent.Length);
+ }
+ ///
+ /// Remove the last indent that was added with PushIndent
+ ///
+ 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;
+ }
+ ///
+ /// Remove any indentation
+ ///
+ public void ClearIndent()
+ {
+ this.indentLengths.Clear();
+ this.currentIndentField = "";
+ }
+ #endregion
+ #region ToString Helpers
+ ///
+ /// Utility class to produce culture-oriented representation of an object as a string.
+ ///
+ public class ToStringInstanceHelper
+ {
+ private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture;
+ ///
+ /// Gets or sets format provider to be used by ToStringWithCulture method.
+ ///
+ public System.IFormatProvider FormatProvider
+ {
+ get
+ {
+ return this.formatProviderField ;
+ }
+ set
+ {
+ if ((value != null))
+ {
+ this.formatProviderField = value;
+ }
+ }
+ }
+ ///
+ /// This is called from the compile/run appdomain to convert objects within an expression block to a string
+ ///
+ 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();
+ ///
+ /// Helper to produce culture-oriented representation of an object as a string
+ ///
+ public ToStringInstanceHelper ToStringHelper
+ {
+ get
+ {
+ return this.toStringHelperField;
+ }
+ }
+ #endregion
+ }
+ #endregion
+}
diff --git a/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/RazorPages/Edit.tt b/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/RazorPages/Edit.tt
new file mode 100644
index 000000000..1df25d584
--- /dev/null
+++ b/src/dotnet-scaffolding/dotnet-scaffold-aspnet/Templates/RazorPages/Edit.tt
@@ -0,0 +1,65 @@
+<#@ template hostSpecific="true" linePragmas="false" #>
+<#@ parameter type="Microsoft.DotNet.Tools.Scaffold.AspNet.Models.RazorPageModel" name="Model" #>
+<#@ import namespace="System.Collections.Generic" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Linq" #>
+<#@ import namespace="Microsoft.DotNet.Tools.Scaffold.AspNet.Extensions" #>
+<#
+ string modelName = Model.ModelInfo.ModelTypeName;
+ string modelNamespace = Model.ModelInfo.ModelNamespace;
+ string modelNameCapitalized = Model.ModelInfo.ModelTypeNameCapitalized;
+ string modelFullName = string.IsNullOrEmpty(modelNamespace) ? modelName : $"{modelNamespace}.{modelName}";
+ var entityProperties = Model.ModelInfo.ModelProperties
+ .Where(x => !x.Name.Equals(Model.ModelInfo.PrimaryKeyName, StringComparison.OrdinalIgnoreCase)).ToList();
+ string primaryKeyName = Model.ModelInfo.PrimaryKeyName;
+ string pageModelFullName = string.IsNullOrEmpty(Model.RazorPageNamespace) ? "EditModel" : $"{Model.RazorPageNamespace}.EditModel";
+#>
+@page
+@model <#= pageModelFullName #>
+
+@{
+ ViewData["Title"] = "Edit";
+}
+
+Edit
+
+<#= modelName #>
+
+
+
+
+
+@section Scripts {
+ @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
+}