EF Code First Migrations causing CA1701 and CA1703 - entity-framework-5

Upon enabling migrations for my code-first EF 5 context I started to receive a TON of CA1701 and CA1703 code analysis violations due to the migration history string being added to the project's resx file.
I do not care to disable CA1701 and CA1703 and also do not want to suppress 100ish messages for each individual migration that's going to be added. Is there a way to mark a resx's xml file or individual resx entry as // <auto-generated /> so this stops happening? If I have to disable the two rules, then so be it just hoping that's not the only sane answer!
TIA
Jason

I personally got fed up with manually keeping my suppressions up to date (after 2 hours), so I wrote the following T4 template:
<## template debug="false" hostspecific="true" language="C#" #>
<## assembly name="System.Core" #>
<## import namespace="System.Linq" #>
<## import namespace="System.IO" #>
<## import namespace="System.Runtime.Remoting.Messaging" #>
<## output extension=".cs" #>
using System.Diagnostics.CodeAnalysis;
<#
var #namespace = CallContext.LogicalGetData("NamespaceHint");
var folder = Path.GetDirectoryName(Host.TemplateFile);
const int timestampLength = 15;
var timestampWildcards = new string('?', timestampLength);
var paths = Directory.EnumerateFiles(folder, timestampWildcards + "_*.cs");
const int timestampUnderscoreLength = timestampLength + 1;
var classNames = from path in paths
let fileName = Path.GetFileNameWithoutExtension(path)
where !fileName.EndsWith(".designer", StringComparison.OrdinalIgnoreCase)
where fileName.Length> timestampUnderscoreLength
select fileName.Substring(timestampUnderscoreLength);
foreach(var className in classNames)
{
var fullClassName = #namespace + "." + className;
#>
[assembly: SuppressMessage("Microsoft.Naming", "CA1701:ResourceStringCompoundWordsShouldBeCasedCorrectly", Scope = "resource", Target = "<#=fullClassName#>.resources")]
[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope = "resource", Target = "<#=fullClassName#>.resources")]
<#
}
#>
Create a T4 template with this content in the same folder as the migrations, the generated code will automatically contain suppressions for the resources, e.g.
[assembly: SuppressMessage("Microsoft.Naming", "CA1701:ResourceStringCompoundWordsShouldBeCasedCorrectly", Scope = "resource", Target = "LzSoftware.Collectables.Domain.EntityFramework.Migrations.InitialCreation.resources")]
[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope = "resource", Target = "LzSoftware.Collectables.Domain.EntityFramework.Migrations.InitialCreation.resources")]
[assembly: SuppressMessage("Microsoft.Naming", "CA1701:ResourceStringCompoundWordsShouldBeCasedCorrectly", Scope = "resource", Target = "LzSoftware.Collectables.Domain.EntityFramework.Migrations.RemovedAdministratorRoleFromSettings.resources")]
[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope = "resource", Target = "LzSoftware.Collectables.Domain.EntityFramework.Migrations.RemovedAdministratorRoleFromSettings.resources")]

I just noticed this today, myself. You can suppress the CA1701 and CA1703 warnings at the resource level with the following in either your AssemblyInfo.cs or a GlobalSuppressions.cs file:
[assembly: SuppressMessage("Microsoft.Naming",
"CA1701:ResourceStringCompoundWordsShouldBeCasedCorrectly",
Justification = "The auto-genererated code from code first migrations trigger this warning.",
Scope = "resource", Target = "Full.Namespace.To.Your.Migrations.NameOfYourMigration.resources")]
[assembly: SuppressMessage("Microsoft.Naming",
"CA1703:ResourceStringsShouldBeSpelledCorrectly",
Justification = "The auto-genererated code from code first migrations trigger this warning.",
Scope = "resource", Target = "Full.Namespace.To.Your.Migrations.NameOfYourMigration.resources")]
You'll need to do this for each of your migrations, but it's much better than suppressing each warning individually.

Related

Why aren't the Template tasks coming in when I create a project using a graph extension / C# code?

I have a customization where I'm creating projects in code using the ProjectEntry graph and
the PMProject DAC:
//create the project graph...
ProjectEntry projentry = PXGraph.CreateInstance<ProjectEntry>();
pmproj = new PMProject();
//Set the ProjectID:
pmproj.ContractCD = "000001"; //Project preferences is set to allow manually created project CDs...
//The template ID...
var tmplt = (PMProject)PXSelect<PMProject,
Where<PMProject.contractCD, Equal<Required<PMProject.contractCD>>>>.Select(Base, "00TEMPLATE01");
pmproj.TemplateID = tmplt.ContractID;
//The description....
pmproj.Description = "Test description";
//Now save the new project...
pmproj = projentry.Project.Insert(pmproj);
projentry.Persist();
It's not picking up the template tasks. Is there something else I need to do to get those tasks to come into the project?
There is a separate method that you need to trigger to populate settings from a project template.
DefaultFromTemplate(Project.Current, newTempleteID, DefaultFromTemplateSettings.Default);
It is executed automatically when you do that from UI, but if you do that from cod you need to do it manually.
Try this alternative approach to the sequence in which the values are entered in the Cache:
ProjectEntry projentry = PXGraph.CreateInstance<ProjectEntry>();
pmproj = new PMProject();
pmproj.ContractCD = "000001";
pmproj = projentry.Project.Insert(pmproj);
var tmplt = (PMProject)PXSelect<PMProject,
Where<PMProject.contractCD, Equal<Required<PMProject.contractCD>>>>.Select(Base, "00TEMPLATE01");
pmproj.TemplateID = tmplt.ContractID;
projentry.Project.Update(pmproj);
pmproj.Description = "Test description";
projentry.Project.Update(pmproj);
projentry.Actions.PressSave();

How to embed scenario name or feature name as a report file name in cucumber extend reporting?

I am using Cucumber-Extent reporting to generate reports for the test execution. In that I am dynamically passing name to the report file. I am able to pass a timestamp as extent report file name in #before of runner class. But I need to pass the scenario name or feature name along with the timestamp. Give me an idea to get the scenario name in runner class and append it to extent report name.
#CucumberOptions( features = "classpath:features",
tags = {"#InsuredInfoScreenAddressValidation"},
glue="classpath:stepDefinition",
plugin = "com.cucumber.listener.ExtentCucumberFormatter:",
"pretty",
"html:target/cucumber-html-report"},
monochrome=true //tags = "#Sample" //tags = "#Testing" )
You can get the name of the Scenario mentioned in the feature file from Scenario object in the #Before hook:
#Before()
public void beforeScenario(Scenario scenario)
{
extent = new ExtentReports (userDir + \\test-output\\" + scenario.getName()+ ".html", true);
}

Change culture for an ASP.NET Core 2 Razor page

I created an ASP.NET Core 2 projects with razor pages and I would like to give the opportunity to the visitor to select a language. The first problem that I had was to change the web application url so that ti will include the current language code. I solved this problem by adding the following code in ConfigureServices.
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.Conventions.AuthorizeFolder("/Account/Manage");
options.Conventions.AuthorizePage("/Account/Logout");
options.Conventions.AddFolderRouteModelConvention("/", model =>
{
foreach (var selector in model.Selectors)
{
var attributeRouteModel = selector.AttributeRouteModel;
attributeRouteModel.Template = AttributeRouteModel.CombineTemplates("{language=el-GR}", attributeRouteModel.Template);
}
});
});
}
}
Now I could visit a page using the following URL:
http://domain/el-GR/MyPage
The last thing that I would like to do is to change the culture of each request. The best solution that I fount which I do not like is to put the following code in my page:
System.Globalization.CultureInfo.CurrentCulture = new System.Globalization.CultureInfo((string)RouteData.Values["language"]);
System.Globalization.CultureInfo.CurrentUICulture = new System.Globalization.CultureInfo((string)RouteData.Values["language"]);
This is not nice because I will have to add these lies in every razor page that I will create in my project.
Is there another way to set the culture for all the requests of my web application?
Refer to this article: https://joonasw.net/view/aspnet-core-localization-deep-dive
There are a few methods, I use the RequestCultureProviders.
NuGet: Microsoft.AspNetCore.Localization
in my Startup.Configure method.
IList<CultureInfo> sc = new List<CultureInfo>();
sc.Add(new CultureInfo("en-US"));
sc.Add(new CultureInfo("zh-TW"));
var lo = new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture("en-US"),
SupportedCultures = sc,
SupportedUICultures = sc
};
var cp = lo.RequestCultureProviders.OfType<CookieRequestCultureProvider>().First();
cp.CookieName = "UserCulture"; // Or whatever name that you like
app.UseRequestLocalization(lo);
Set your cookie "UserCulture" to "c=zh-TW|uic=zh-TW" once.
And it works magically.

How to test a IAppSettings in ServiceStack?

In ServiceStack there is an IAppSettings as follows:
var appSettings = new AppSettings();
DateTime lastUpdate = appSettings.Get<DateTime>("LastUpdated");
IList<string> allowedUsers = appSettings.GetList("AllowedUsers");
var redisConf = appSettings.Get<RedisConfig>("RedisConf");
How can I create an instance of AppSettings with properties in code?
I want to create a IAppSettings in code for testing and not to take the values from a configuration file, e.g., web.config.
You could also use a mocking framework like moq to stub out the implementation of the IAppSettings interface:
var appSettings = new Mock<IAppSettings>();
appSettings.Setup(s => s.Get<DateTime>("LastUpdated")).Returns(new DateTime(2015, 2, 1));
Then, in your test, just pass appSettings.Object to any service/component that needs an IAppSettings.
The different IAppSettings providers are listed AppSettings Docs, e.g. the DictionarySettings lets you populate the settings from a .NET Dictionary<string,string>.
The AppSettingsTests will also be helpful to see how to test different AppSettings providers.

How to access all ASP.NET Identity 2.0 PasswordValidator properties?

I set multiple properties on the PasswordValidator, but the only rule that is checked is password length.
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator()
{
RequiredLength = int.Parse(ConfigurationManager.AppSettings["PasswordRequiredLength"]),
RequireNonLetterOrDigit = bool.Parse(ConfigurationManager.AppSettings["PasswordRequireNonLetterOrDigit"]),
RequireDigit = bool.Parse(ConfigurationManager.AppSettings["PasswordRequireDigit"]),
RequireLowercase = bool.Parse(ConfigurationManager.AppSettings["PasswordRequireLowercase"]),
RequireUppercase = bool.Parse(ConfigurationManager.AppSettings["PasswordRequireUppercase"])
};
This is pretty much copied from the ASP.NET Identity sample app except the values are from config instead of hard-coded.
When I view the definition of PasswordValidator() I see that these properties are all defined (and it compiles and runs of course). However, I notice when I test changing a password that only the length causes validation error. The AccountController had this code from the sample:
IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
To get a better look I added
IdentityResult resultPassword = await UserManager.PasswordValidator.ValidateAsync(model.NewPassword);
if (resultPassword.Succeeded)
{
IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
and I notice that userManager.PasswordValidator is of class MinimumLengthValidator, not the PasswordValidator I thought we started with. Of course, this explains the behavior, but I am at a loss to determine how to
Correctly add the "full" PassordValidator to my userManager and/or
Access the properties of the PassordValidator (such as RequireDigit, RequireUppercase, etc.)
Note, I have attempted
PasswordValidator myPV = (PasswordValidator)UserManager.PasswordValidator;
which results in a Unable to cast object of type 'Microsoft.AspNet.Identity.MinimumLengthValidator' to type 'Microsoft.AspNet.Identity.PasswordValidator' error.
Best,
Scott

Resources