Suppress CA1303 fxcop warning when constructing a new Exception - c#

When I throw an exception in my ASP.NET Core 3.1 code, fxcop warns me when it sees a string literal as an argument to a new Exception(). For example:
throw new InvalidOperationException("Ouch");
gives me CA1303: Do not pass literals as localized parameters
As a general rule, I don't display exception messages to end users, so I have no desire to localize them. Is there a way to configure CA1303 so that it ignores constructor arguments on anything that derives from System.Exception?
EDIT:
After a bit more searching, I've found this conversation about exactly this problem:
https://github.com/dotnet/roslyn-analyzers/issues/2933

If you are using .editor config, you could do this: dotnet_code_quality.CA1303.use_naming_heuristic = true
Or completely disable CA1303.

Version 3.3.0 of Microsoft.CodeAnalysis.FxCopAnalyzers finally fixed the ability to suppress the warning when calling specific types.
In order to suppress CA1303 when constructing an Exception or when calling an ILogger function, I added a .editorconfig file to the root directory of my solution (all of the projects are subdirectories of this directory) and added these lines to it:
[*.cs]
dotnet_code_quality.CA1303.excluded_type_names_with_derived_types = Exception|LoggerExtensions|ILogger
This tells CA1303 to ignore calls into Exception, LoggerExtensions, and ILogger (and any type that derives from these types).
For reference, see this issue and the reply beneath it:
https://github.com/dotnet/roslyn-analyzers/issues/2933#issuecomment-627256340

Related

Unknown exception at declaration and initalisation of a Class

The main Problem is completely different, please skip to the Edit
I have an exception of an unknown type which doesn't even get thrown properly. Following Code provides the Context:
MMDataAccess.InitDemoDB();
MMDataAccess.InitInternalDB();
MMDataAccess.InitMaintDB();
try
{
SQLiteToDBLib sqltdbl = new SQLiteToDBLib();
sqltdbl.WriteToSQLite();
}
catch(Exception ex)
{
string message = ex.Message;
}
These are the very first lines of my first Activity in my app. The first 3 lines belong to my very own implementation of an in-memory database and are behaving nicely. The problem rises with the next two lines inside the try-block. The declaration and initalistation of the sqltdbl variable never happens. The constructor of SQLiteToDBLib looks like this:
public SQLiteToDBLib()
{
msc = new MSConnection();
}
The MSConnection class doesn't even have a constructor (except for the default one of course).
As you can see i've tried to catch any exceptions, but without success. everything i can figure out is, that a exception is thrown because of the debugger going into the catch section while ignoring everything that has to do with "ex". Without breakpoints everything seems fine. Just without the call to WriteToSQLite which should create a .sqlite file on the external Memory.
What can I do to resolve this error? Is there anything i can catch except the default Exception?
Edit:
After some testing with commented code something interresting happened. I could step into commented code. Well not exactly the commented code, but the code that was there before my changes. Visual Studio somehow shows me the things, that are changed in the file, but is compiling the old code. Up to now i tried to rebuild, clean and build the project in various combinations, unload and reload the project, Restart Visual Studio and restart Windows. Nothing has changed so far. I Will now proceed to create a new .cs File With the exact same Code. I'm working with VS 2013 Community
add static constructor to your SQLiteToDBLib class and perform all static objects initialization in it:
static SQLiteToDBLib()
{
// initialize static members here
}
If this doesn't give you a clue, try enabling CLRE exceptions-break in visual-studio:
DEBUG
Exceptions
Check the 'Common Language Runtime Exceptions' option (under the 'Thrown' column)
Press OK
Restart your app and try again

Executable fails with weird exception

I am using ILMerge and Quartz.NET in a C# .NET 4.0 Windows Service application. The app runs fine without using ILMerge, but now that we're nearing shipping release, I wanted to combine all DLLs into a single executable.
Problem is, that ILMerge seems to work fine, but when I run the combined executable, it throws this exception:
Unhandled Exception: Quartz.SchedulerException: ThreadPool type 'Quartz.Simpl.SimpleThreadPool' could not be instantiated. ---> System.InvalidCastException: Unable to cast object of type 'Quartz.Simpl.SimpleThreadPool' to type 'Quartz.Spi.IThreadPool'.
at Quartz.Util.ObjectUtils.InstantiateType[T](Type type) in :line 0
at Quartz.Impl.StdSchedulerFactory.Instantiate() in :line 0
--- End of inner exception stack trace ---
at Quartz.Impl.StdSchedulerFactory.Instantiate() in :line 0
at Quartz.Impl.StdSchedulerFactory.GetScheduler() in :line 0
Does anyone have any idea why this is? I have been wasting over 4 hours already and I can't figure it out. If I don't combine with ILMerge, then everything runs fine (with the Quartz.dll and Common.Logging.dll in the same directory).
I'm sure someone must have tried packaging Quartz.net up like this before, any ideas?
Disclaimer: I don't know Quartz.NET at all, although I spent some time struggling with ILMerge. When I finally understood its limitations... I stopped using it.
ILMerge'd application tends to have problems with everything which contains the word "reflection".
I can guess (I've never used Quartz.NET) that some classes are resolved using reflection and driven by configuration files.
Class is not only identified by its name (with namespace) but also by assembly it is coming from (unfortunatelly it doesn't get displayed in exception message).
So, let's assume you had (before ILMerging) two assemblies A (for you Application) and Q (for Quartz.NET).
Assembly 'A' was referencing assembly 'Q' and was using a class 'Q:QClass' which was implementing 'Q:QIntf'.
After merging, those classes became 'A:QClass' and 'A:QIntf' (they were moved from assembly Q to A) and all the references in code has been replaced to use those (completely) new classes/interfaces, so "A:QClass" is implementing "A:QIntf" now.
But, it did not change any config files/embedded strings which may still reference "Q:QClass".
So when application is reading those not-updated config files it still loads "Q:QClass" (why it CAN find it is a different question, maybe you left assembly 'Q' in current folder or maybe it is in GAC - see 1).
Anyway, "Q:QClass" DOES NOT implement "A:QIntf", it still implements "Q:QIntf" even if they are binary identical - so you can't cast 'Q:QClass' to 'A:QIntf'.
The not-ideal-but-working solution is to "embed" assemblies instead of "merging" them. I wrote a open-source tool which does it (embedding instead of merging) but it is not related to this question. So if you decide to embed just ask me.
You can test it by removing (hiding, whatever works for you) every single instance of Q.dll on your PC. If I'm right, the exception should say now 'FileNotFound'.
You could try creating your own ISchedulerFactory and avoid using reflection to load all of your types.
The StdSchedulerFactory uses this code to creat a threadpool. It's where your error is happening and would be the place to start looking at making changes:
Type tpType = loadHelper.LoadType(cfg.GetStringProperty(PropertyThreadPoolType)) ?? typeof(SimpleThreadPool);
try
{
tp = ObjectUtils.InstantiateType<IThreadPool>(tpType);
}
catch (Exception e)
{
initException = new SchedulerException("ThreadPool type '{0}' could not be instantiated.".FormatInvariant(tpType), e);
throw initException;
}
The ObjectUtils.InstantiateType method that is called is this one, and the last line is the one throwing your exception:
public static T InstantiateType<T>(Type type)
{
if (type == null)
{
throw new ArgumentNullException("type", "Cannot instantiate null");
}
ConstructorInfo ci = type.GetConstructor(Type.EmptyTypes);
if (ci == null)
{
throw new ArgumentException("Cannot instantiate type which has no empty constructor", type.Name);
}
return (T) ci.Invoke(new object[0]);
}
Right after this section in the factory, datasources are loaded using the same pattern and then the jobs themselves are also loaded dynamically which means you'd also have to write your own JobFactory. Since Quartz.Net loads a bunch of bits and pieces dynamically at runtime going down this road means you might end up rewriting a fair amount of things.

How do I make CloudConfigurationManager.GetSetting less verbose?

I'm currently using CloudConfigurationManager.GetSetting("setting") to get settings for my application, but it's writing logs of everything it's checking to the console (in both Debug and Release):
Getting "setting" from ServiceRuntime: FAIL.
Getting "setting" from ConfigurationManager: PASS (Data Source=...
Getting "setting" from ServiceRuntime: FAIL.
Getting "setting" from ConfigurationManager: PASS (Data Source=...
Is there any way to prevent it from doing this, or an alternative version that's less verbose?
Mostly I just like my unit test output to be nice and clean, but I'm also a little concerned that it's printing out things like connection strings (and hence passwords) in plain text on the production server.
CloudConfigurationManager.GetSetting now has a method overload with a parameter called outputResultsToTrace.
If you pass false to this method, then it'll disable the Trace.WriteLine used elsewhere to "spam" the Trace log.
So
var mySetting = CloudConfigurationManager.GetSetting("MySetting");
becomes
var mySetting = CloudConfigurationManager.GetSetting("MySetting", false);
I found this by looking directly at the source code on GitHub: https://github.com/Azure/azure-sdk-for-net/blob/52fc67253a176bea01c37c164f71c7eba8eaedba/src/Common/Configuration/CloudConfigurationManager.cs#L35
It's probably worth mentioning that this overload is not documented: https://msdn.microsoft.com/en-us/library/azure/mt634648.aspx
So I'm not sure if it's an official and supported part of the API, or if it's something that might change or go away in the future.
This change was made at the end of 2015: https://github.com/Azure/azure-sdk-for-net/commit/e14398136d7d3b6d5e4675f1e8ccbdd37a8c6b01
Not really. If you look at the code of the underlying GetValue method you'll see this:
private static string GetValue(string providerName, string settingName, Func<string, string> getValue)
{
string str1 = getValue(settingName);
string str2;
if (str1 != null)
str2 = string.Format((IFormatProvider) CultureInfo.InvariantCulture, "PASS ({0})", new object[1]
{
(object) str1
});
else
str2 = "FAIL";
Trace.WriteLine(string.Format((IFormatProvider) CultureInfo.InvariantCulture, "Getting \"{0}\" from {1}: {2}.", (object) settingName, (object) providerName, (object) str2));
return str1;
}
The Trace.WriteLine is always called without taking into account Debug or Release. Now you can simply remove the Default listener which should suppress all messages:
<system.diagnostics>
<trace>
<listeners>
<remove name="Default" />
</listeners>
</trace>
</system.diagnostics>
Now if you look at the CloudConfigurationManager it doesn't do that much. If this is a problem for you you can cook up something yourself, starting with this:
if (RoleEnvironment.IsAvailable)
return RoleEnvironment.GetConfigurationSettingValue(setting);
else
return ConfigurationManager.AppSettings[setting];
Note: The CloudConfigurationManager does a lot more than this, like loading the assembly without assembly reference.
Alternative option, if you're calling CloudConfigurationManager.GetSetting() in one part (ie, a wrapper/helper class):
var oldListeners = Trace.Listeners.Cast<TraceListener>().ToArray();
Trace.Listeners.Clear();
var stringValue = CloudConfigurationManager.GetSetting(key);
Trace.Listeners.AddRange(oldListeners);
First, we remove all listeners on Trace. Then we grab the setting, and re-add the listeners. Of course, this potentially could cause problems with threaded applications
I just installed the nuget package Microsoft.WindowsAzure.ConfigurationManager version 3.1.0, and I can confirm that the issue has been fixed in this version. Taking a look at the github issue referenced in the question's comments, we can see, in the changelog, the fetched value is no longer written to the trace output. In particular, the trace message has been changed from:
message = string.Format(CultureInfo.InvariantCulture, "PASS ({0})", value);
to:
message = "PASS";
This still makes the configuration manager quite verbose though.
We just ran into this ourselves...so very frustrating.
We can't remove the default listener because we are logging our own stuff on it.
There is an easy workaround though. Just use the good old fashioned ConfigurationManager.AppSettings["Microsoft.ServiceBus.ConnectionString"] and you will get the info you need without the annoying logging.
Hope that helps,
David
I had quite similar problems. I updated from Azure SDK 2.0 to 2.2 - during this process I used the NuGet Manager to update the Microsoft.WindowsAzure.Storage to the latest. The PackageManager automatically took Microsoft.WindowsAzure.Configuration to 1.8.0.0. I was not able to get this running (it was for .Net 2.0!?). After I manually set all References to
Microsoft.WindowsAzure.Storage 2.1.0.0
Microsoft.WindowsAzure.Configuration 2.0.0.0
everything worked.
I think this is because of the way CloudConfigurationManager.GetSetting loads the assembly and calls the funktions (via reflection).
Fixed in version 3.0.0. Please update Microsoft Azure Configuration Manager nuget package.
There are two separate issues here:
Setting values are logged in plain text (a security concern)
Messages are logged every time a setting is retrieved (a verbosity concern)
As others have noted, #1 has been fixed in a more recent version of the plugin.
Based on my experience (and some of the other responses here), #2 is still a huge annoyance.
Looking at WADLogsTable in Visual Studio's Queue Editor, note that the message level is 5 (i.e. verbose, according to this list of ETW levels).
Going off of the diagnostic config file schema, my approach to solving issue #2 was to limit the minimum severity level (e.g. warning, informational, verbose) of generic tracing to "information" (or more severe) and just ensure my own logging did not use the "verbose" level.
Here is the change I made in diagnostics.wadcfgx:
Original:
<Logs scheduledTransferPeriod="PT1M" scheduledTransferLogLevelFilter="Verbose" />
Fixed:
<Logs scheduledTransferPeriod="PT1M" scheduledTransferLogLevelFilter="Information" />

Code Contract : ccrewrite exited with code -1?

I'm new to code contracts. I downloaded the latest build of code contract project (1.4.40314.1) and started to implement it in my project. When i enabled 'Runtume Checking' through Code Contracts Tab in VS2010, i got this Error
Error 1 The command ""C:\Program Files (x86)\Microsoft\Contracts\Bin\ccrewrite" "#Application1ccrewrite.rsp"" exited with code -1.
everytime i build the project. Plz help.
Now it's a major problem for me.
Every project using code contracts is showing same error in VS2010 Errors window and 'Application1ccrewrite.rsp' not found in output window, but it is there.
I tried out everything. I installed both versions (Pro, Std) but the problem persist. Plz help !
I had this problem as well. In my case the problem was that ccrewrite cannot work with files in a network folder but requires the project to be on your local hard disk.
I had this problem. The Assembly name and Default namespace of the class library that causes the problem had the same name as an existing DLL in the destination folder. I had been refactoring my code and whilst the namespaces in the CS files had all be changed to namespace2 the default namespace in the properties file was still namespace1
When I corrected this the files all built successfully...
Sometimes you can get this when your solution path is too long, especially with many projects.
Try moving to c:\temp and building it, it might fix it (although of course, this might not be a solution if you need it in the folder it currently is).
This bug I noticed in earlier CC versions and may now be fixed.
I don't know if you had the same problem as me, but I also saw this error. In my case, I had a method with a switch statement, and depending on the branch taken, different requirements applied:
static ITransaction CreateTransaction(
String transType,
MyType1 parm1,
/* Other params unimportant to this example */
String parm5)
{
switch (transType) {
case Transaction.Type.SOME_TRANSFER:
Contract.Requires<ArgumentNullException>(parm1.Account != null, "Account cannot be null.");
Contract.Requires<ArgumentException>(!String.IsNullOrWhiteSpace(parm5), "parm5 cannot be null or empty.");
// Create instance
return someInst;
case Transaction.Type.SOME_OTHER_TRANSFER:
Contract.Requires<ArgumentException>(!String.IsNullOrWhiteSpace(parm1.Type), "Type cannot be null or empty.");
Contract.Requires<ArgumentException>(!String.IsNullOrWhiteSpace(parm1.Number), "Number cannot be null or empty.");
// Create instance
return someInst;
/* Other cases */
default:
throw new ApplicationException("Invalid or unknown transaction type provided.");
}
}
This was giving me the error you noted in the Errors List when I tried to build. In the output window, I was getting this:
EXEC : Reference Assembly Generator
warning : Something is wrong with
contract number 1 in the method
'TerraCognita.LoanExpress.Domain.Loan.CreateLoanTransaction'
AsmMeta failed with uncaught
exception: Operation is not valid due
to the current state of the object.
I pushed each branch into a method of its own, making Contract.Requires the first lines of code in each method, and I no longer had a compilation problem. It appears that Contract.Requires must be the first lines of code in a method - which makes sense, since they are intended to be used to define pre-conditions.
Hope this helps.
The solution is to put the pre and pos conditions in the first lines. The ccrewrite does not accept that pre and post conditions are below command lines.

How to suppress a StyleCop warning?

I'm using StyleCop and want to suppress some warning which does not suit my style. I prefer to have solution for
1) in-line code suppressing
2) global setting suppressing
I've searched the internet but still not sure how to do the suppressing.
For method 1), They said to add the lines:
[assembly: SuppressMessage("Microsoft.Design",
"SA1202:All private methods must be placed after all public methods",
Scope = "namespace", Target = "Consus.Client.ClientVaultModule.Services.OnlineDetection")]
But they do not say where and which namespace to be used.
For method 2), they said to use GlobalSuppress file but it seems not easy to search for a how-to do it at the moment.
Please help.
[Edited]
In my case, I have the warning about SA1202: All private methods must be placed after all public methods which is bothering since I group my related codes into regions. I want to suppress those warning for just some certain methods.
Here's what you need:
[SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess")]
An example of inline suppression would be similar to this - examine the namespaces in the code compared to the suppression
namespace Soapi
{
///<summary>
///</summary>
///<param name = "message"></param>
///<param name = "statusCode"></param>
///<param name = "innerException"></param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object)")]
public ApiException(string message, ErrorCode statusCode, Exception innerException)
: base(String.Format("{0}\r\nStatusCode:{1}", message, statusCode), innerException)
{
this.statusCode = statusCode;
}
A global supression file is a file in the root of your project named GlobalSuppressions.cs and might look like this:
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.
//
// To add a suppression to this file, right-click the message in the
// Error List, point to "Suppress Message(s)", and click
// "In Project Suppression File".
// You do not need to add suppressions to this file manually.
[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.String.Format(System.String,System.Object,System.Object,System.Object)", Scope = "member", Target = "Soapi.ApiException.#.ctor(System.String,Soapi.ErrorCode,System.String,System.Exception)")]
And you can generate this code automatically by right-clicking on the warning.
Starting with StyleCop 4.3.2, it is possible to suppress the reporting of rule violations by adding suppression attributes within the source code.
Rule Suppressions
http://stylecop.soyuz5.com/Suppressions.html
but it says -
Global Suppressions
StyleCop does not support the notion of global suppressions or
file-level suppressions. Suppressions must be placed on a code
element.
If you've installed StyleCop, you can right-click your project and there will be a StyleCop option. Click this and you'll see you can prevent certain rules from even running against your project. Moreover, you can create a separate rules file to share between different projects. This means you can configure the rules once the way you want them and then share that configuration between all your projects.
For individual overrides, SuppressMessage is the way to go.
Go to Solution Explorer
Go to your project
Expand references
Expand Analyzers
Expand StyleCop.Analyzers
Right click on a particular rule which you want to disable at a global (project) level
Set Rule Set severity -> Select None
Read the admonition from Style Cop, looking for the alphanumeric code. In your case 'SA1202'. Then browse to the corresponding page on the Style Cop website. Change the URL as appropriate https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1202.md
Copy the line labelled 'How to Suppress Violations'. Paste the attribute above the class about which Style Cop moans
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess", Justification = "Reviewed.")]
Cant you just remove the rule instead of soiling your code?
Same goes for FxCop...
1.
In your case, correct SuppressMessage attribute should like like the following:
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess")]
private void SomeMethod()
{
}
Note that you can place it on any other element (e.g, on the class - then all similar violations in the entire class will be supressed).
I also agree that it's quite unobvious what to write in these fields.
Actually, the first one should be the fully qualified name of StyleCop analyser class and could be found from the source code (e.g. from here).
The second one should start with rule code, then colon and the name of the rule enumeration (luckily, it always looks like the rule name displayed in the Settings Editor, but with no whitespaces).
2.
Regarding suppressing rules "globally" - why don't just turn them off via Settings Editor? Settings files are inherited through the file system, so you could easily have one "main" settings file at the "top" of your folder structure, and some other files (holding the "difference" from main) with exceptions made for some projects, if you want so (like described here).
Good luck!
You can disable the rules you don't want in Settings.StyleCop file, which is in the project root folder.
You will need the namespace that contains the rule, which can be found here:
http://stylecop.soyuz5.com/StyleCop%20Rules.html
Settings.stylecop file code for your reference:
<StyleCopSettings Version="105">
<Analyzers>
<Analyzer AnalyzerId="StyleCop.CSharp.LayoutRules">
<Rules>
<Rule Name="ElementsMustBeSeparatedByBlankLine">
<RuleSettings>
<BooleanProperty Name="Enabled">False</BooleanProperty>
</RuleSettings>
</Rule>
</Rules>
<AnalyzerSettings />
</Analyzer>
</Analyzers>
</StyleCopSettings>
Alternatively you could move the code in regions into partial classes. Then the issue with the stylecop rule will go away.
In addition to the helpful answers already in place:
If you suppress a warning in the suppression file GlobalSuppressions.cs,
you can edit that [assembly: SuppressMessage(StyleCop...blabla line and entirely remove the Scope=... and Target=... tags. That makes the suppression global in the project.
The README.md for the StyleCop.Analyzers NuGet package used by Visual Studio 2015+ contains a link to the documentation for the rules. The documentation for each rule contains a "How to suppress violations" section. For the SA1202 rule, the options are:
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess", Justification = "Reviewed.")]
and
#pragma warning disable SA1202 // ElementsMustBeOrderedByAccess
#pragma warning restore SA1202 // ElementsMustBeOrderedByAccess

Categories