Visual Studio 2012 install broke my 2010 WCF project - wcf

I've installed VS 2012 and am successfully using it on some web projects, but something with it has caused my web service project to break. I'm still using VS 2010 on the web service project and have not opened it in 2012.
Everything compiles and works correctly except when it tries to create an instance of a class in my referenced weblog project, then it throws this error:
This method or property is not supported after HttpRequest.GetBufferlessInputStream has been invoked.
I can not find anywhere in the project where GetBufferlessInputStream is used explicitly.
If I jump over the weblog code, everything executes correctly.
I can't find anyone else who has received this error to try and narrow it down, any ideas where to start?
Stack
at System.Web.HttpRequest.get_InputStream()
at OAS.Web.Log.WebEvent..ctor(EventType type, HttpContext context, String applicationName)
at OAS.Web.Log.WebTrace..ctor(HttpContext context, String applicationName)
at OAS.Web.AdvisorServices.Extensions.OperationLoggerParameterInspector.BeforeCall(String operationName, Object[] inputs) in C:\SourceControl\OAS\IM.NET3.0\Web\AdvisorServices\OAS.Web.AdvisorServices.Extensions\OperationLogger\OperationLoggerParameterInspector.cs:line 54
**EDIT - Bonus Question
Why are these Framework 4.5 properties affecting my 4.0 solution?

Note : This issue has been fixed in .net 4.5.1. You can see the fix with 4.5.1. Once you have .net 4.5.1 add the following appSetting to switch back to the old behavior.
<configuration>
<appSettings>
<add key="wcf:serviceHostingEnvironment:useClassicReadEntityBodyMode" value="true" />
</appSettings>
</configuration>
Here is how you can create a HttpModule to force ReadEntityBodyMode to be "classic" : http://blogs.msdn.com/b/praburaj/archive/2012/09/13/accessing-httpcontext-current-request-inputstream-property-in-aspnetcompatibility-mode-throws-exception-this-method-or-property-is-not-supported-after-httprequest-getbufferlessinputstream-has-been-invoked.aspx
To answer your other question (Why are these Framework 4.5 properties are effecting my 4.0 solution?):
.net 4.5 is an in-place upgrade of .net 4.0. So even if your project is targeting 4.0, since VS 2012 installs 4.5 runtime, some of the 4.5 behaviors take effect.
EDIT
Blog Entry:
In .net 4.5 WCF leveraged the buffer less input stream for scalability benefits. As a result when you try to access the HttpContext.Current.Request.InputStream property you may end up with the below exception, as the InputStream property tries to get you handle to the Classic stream as they both are incompatible.
“This method or property is not supported after
HttpRequest.GetBufferlessInputStream has been invoked.”
If you had a WCF 4.0 app which worked perfectly but on upgrading your .net framework to 4.5 you notice the service failing on accessing this property, here is the way to work-around the issue:
Add a simple HttpModule in the same WCF project which will access the InputStream property for each request before WCF reads it so that it will enforce the HttpContext.Request.ReadEntityBody to be "Classic" and will ensure compatibility.
public class WcfReadEntityBodyModeWorkaroundModule : IHttpModule
{
public void Dispose() { }
public void Init(HttpApplication context) {
context.BeginRequest += context_BeginRequest;
}
void context_BeginRequest(object sender, EventArgs e) {
//This will force the HttpContext.Request.ReadEntityBody to be "Classic" and will ensure compatibility..
Stream stream = (sender as HttpApplication).Request.InputStream;
}
}
Register this module in your web.config by adding these lines in <configuration> <modules> setting.
<system.webServer>
<modules>
<!-- Register the managed module -->
<add name="WcfReadEntityBodyModeWorkaroundModule" type="MyAssembly.WcfReadEntityBodyModeWorkaroundModule, MyAssembly" />
</modules>
If you are using an app pool in classic mode, you will need to add the module to this section in the web.config:
<system.web>
<httpModules>
<add name="WcfReadEntityBodyModeWorkaroundModule" type="MyAssembly.WcfReadEntityBodyModeWorkaroundModule, MyAssembly" />
</httpModules>
If your project cannot be modified, then you can write this Http module in a separate assembly, GAC it separately and register this module in the web.config.
Now try accessing the service it should succeed for you!

Related

How to read web.config file in .Net Core app

I have created a .Net Core API and I referenced a .Net framework application to it. The referenced Application connects to a data base and its connection string is stored in web.config file:
string CONNSTR =ConfigurationManager.ConnectionStrings["SHOPPINGCNN"].ConnectionString;
The .Net Core application uses appsettings.json instead of web.config file. When I run the API and try to use the referenced application resources, the above code will be triggered and will return null because there is no web.config file exists in .net Core app. What is the best solution to resolve this issue
Because .Net Core applications are self hosted and can almost run on any platform, they are no longer hosted on IIS. The .Net Core application settings are stored in a Json format (appsettings.json) by default while .Net Framework application configurations are stored in a web.config file in XML format. For more info about .Net Core applications, you may read Configuration in ASP.NET Core. In my case, I was trying to access the data layer of a .Net Framework assembly from a .Net Core 2.0 assembly. To achieve this, there is no need to install System.Configuration.ConfigurationManager package in the .Net Core application but you only need to add app.config to the .Net Core assembly then add the connection string to it:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="SHOPPINGCNN" connectionString="server=your server name;integrated security=true;database=your database name" />
</connectionStrings>
</configuration>
After that, everything will work fine. Make sure that you use the same connection string name (SHOPPINGCNN in my case) that you used in your .Net Framework application otherwise you will not get the desired result. I did this in my project and it works 100%.
in .net core you can use ConfigurationBuilder to read appsettings.json file.
You can implement like following.
appsettings.json sample
{
"option1": "value1_from_json",
"option2": 2,
"ConnectionStrings": {
"YourConnectionString": "............."
}
}
C# code sample
static class YourClass
{
public static IConfigurationRoot Configuration;
public static string GetConnectionString()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json");
Configuration = builder.Build();
var connectionString = Configuration["ConnectionStrings:YourConnectionString"];
}
}
In case you missed it - and because #Zuhair doesn't seem to want to post an answer - here is a copy paste of their solution (I missed this at first as it was only in a comment):
I found the solution. I changed the name of the Web.config to
app.config and I was able to get the connection string using:
System.Configuration.ConfigurationManager.ConnectionStrings["SHOPPINGCNN"].ConnectionString
The app.config file looks like this:
<?xml version="1.0"> encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="SHOPPINGCNN" connectionString="server=.\SQLEXPRESS;integrated security=true;database=xxxxx" />
</connectionStrings>
</configuration>
You also need to install this NuGet package:
System.Configuration.ConfigurationManager
In my case I simply renamed the web.config containing the connectionString 'app.config' and it worked.
I realise this probably isn't a good long term solution but for mixed legacy projects - or to get a foot in the door to begin to learn .net Core it's very useful.
For .NET Core apps, the best way is to use the Configuration API. This is a very flexible way and, thanks to providers pattern, it allows to use a different sources, not only the most common appsettings.json file (that by the way just a JSON file and could be named in a random way):
File formats (INI, JSON, and XML)
Command-line arguments
Environment variables
In-memory .NET objects
An encrypted user store Azure Key Vault
Custom providers, which you install or create
Now about ConfigurationManager . At first, the .NET Core forced to forget about this class - it was not implemented and supported and the idea was to fully replace it by providing new Configuration API.
Moreover, the reality is that ASP.NET Core apps aren't hosted via IIS anymore (IIS works mainly as a reverse proxy now), and so the web.config is not so useful anymore (unless rare cases when you still need to define parameters specific to IIS configuration).
Though, after the .NET Standard 2.0 was provided, this System.Configuration.ConfigurationManager nuget package is available and brings back the ConfigurationManager class. It became possible due to new compatibility shim implemented in new .NET Core 2.0.
Regarding your case, it is difficult to say why you have 'null' as it not enough information:
it may be a wrong section in web.config
web.config may not be copied into your output/publishing folder
The problem here is that the OP has a data access layer project library that targets the full .Net Framework that contains code which depends on the ConfigurationManager. ConfigurationManager knows nothing about configuration in .Net Core and thus cannot access values from the default configuration implementation, i.e. appsettings.json. Some answers note that you can add an app.config file to the .Net Core client, but this smells if we don't hold our nose.
The better solution would be to inject the connection string into the data access library. Especially if that library will be used by multiple clients.
For everyone having problem reading web.config in asp.net core. After spending hours trying and failing.. then i came to a blog which stated
The .Net Core application uses appsettings.json instead of web.config
file.
so i suggest everyone to place files they want to read to appsettings.json and from there you can read. There are plenty of methods available. Just wanted to save time of those trying.
The only way i could use a web.config was reading the file as a XML, and inputing the values into a ConfigurationManager object using the .AddInMemoryCollection(list) method.
//ConfigurationManager.cs
using System;
using System.Collections;
using System.Xml;
using Microsoft.Extensions.Configuration;
namespace sql_util {
public static class ConfigurationManager {
public static IConfiguration AppSettings { get; }
static ConfigurationManager() {
var list = new List<KeyValuePair<string, string>>();
XmlDocument xd = new XmlDocument();
xd.Load(Directory.GetCurrentDirectory() + "\\" + "web.config");
if (xd.GetElementsByTagName("appSettings").Count > 0) {
XmlNodeList confs = xd.GetElementsByTagName("appSettings")[0].ChildNodes;
for (int y = 0; y < confs.Count; y++) {
if (confs[y].Attributes != null) {
if (confs[y].Attributes[0] != null) {
list.Add(new KeyValuePair<string, string>(confs[y].Attributes[0].Value, confs[y].Attributes[1].Value));
}
}
}
}
AppSettings = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddXmlFile(Directory.GetCurrentDirectory() + "\\Web.config", false, true)
.AddInMemoryCollection(list)
.Build();
}
}
}
//Web.config
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appSettings>
<add key="smtp_server" value="127.0.0.1" />
//envia_mail.cs
using ConfigurationManager = sql_util.ConfigurationManager;
namespace anotacoes {
public class envia_email {
private string SmtpServer = ConfigurationManager.AppSettings["smtp_server"];
added Web.config file to root as i used in .net framework project.
ConfigurationManager.AppSettings["MySQL"]; works fine.
I changed my Web.config to App.config and my issues resolved immediately.
You can still use an app.config for connection strings if needed. Include the nuget package System.Configuration.ConfigurationManager.
Then to get a connection string you'd do this:
System.Configuration.ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString
As others have pointed out, connection strings are easily used from the appsettings.json file and this is the preferred method.

ELMAH for ASP .NET MVC Windows Application

I need to log errors for an asp.net mvc windows application which also uses entity framework and for doing this i thought of using ELMAH.
My App.config file contains the appsettings for providing folderpath and other file related details.
Now when I try to add the configuration (elmah...../elmah) for ELMAH after installing it in my project it throws an exception "Configuration system failed to initialize".
But when I remove that code then it works fine.
Please provide me the solution to log errors for MVC windows application.
And the final question is ELMAH.mvc free to use or not?
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="folderpath" value="~PA\FileImport"/
<add key="XMLFolderPath" value="~\FileImport\XML"/>
</appSettings>
<connectionStrings>
<add name="####" connectionString="############"
providerName="System.Data.EntityClient" />
</connectionStrings>
<elmah>
..........
</elmah>
</configuration>
It sounds like there's a problem with your ELMAH configuration, since ELMAH and EntityFramework normally doesn't interfere with each other. I would recommend you to follow a tutorial like this: ELMAH Tutorial. There's a ton of tutorials for ELMAH outthere, why a simple google search will find a lot of resources.
If following a tutorial doesn't work, you should probably add some additional information and web.config code in this thread, since figuring out your problem from the amount of information, is almost impossible.

How to configure machineKey in Custom Membership to use MD5 for ASP.MVC 4 (net 4.5)?

I'm implementing a CustomMembership Provider, and the first part works, login, register, etc.(I chosen the validationKey and decriptionKey for now from http://msdn.microsoft.com/en-us/library/vstudio/w8h3skw9(v=vs.100).aspx).
My Web.Config:
<system.web>
<machineKey validationKey="32E35872597989D14CC1D5D9F5B1E94238D0EE32CF10AA2D2059533DF6035F4F" decryptionKey="B179091DBB2389B996A526DE8BCD7ACFDBCAB04EF1D085481C61496F693DF5F4"/>
<membership defaultProvider="CustomMembershipProvider">
<providers>
<clear />
<add name="CustomMembershipProvider" type="CustomMembership.CustomMembership.CustomMembershipProvider" connectionStringName="TestMembershipEntities" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" passwordFormat="Encrypted" />
</providers>
</membership>
<roleManager enabled="true" defaultProvider="CustomRoleProvider">
<providers>
...
Now I need to use MD5.
The method EncryptPassword choose the right Algorithm, if I set validation attribute in MachineKey?
switch (PasswordFormat)
{
case MembershipPasswordFormat.Clear:
break;
case MembershipPasswordFormat.Encrypted:
byte[] encryptedPass = EncryptPassword(Encoding.Unicode.GetBytes(password));
encodedPassword = Convert.ToBase64String(encryptedPass);
break;
case MembershipPasswordFormat.Hashed:
HMACSHA1 hash = new HMACSHA1();
hash.Key = HexToByte(machineKey.ValidationKey);
encodedPassword = Convert.ToBase64String(hash.ComputeHash(Encoding.Unicode.GetBytes(password)));
break;
default:
throw new ProviderException("Unsupported password format.");
}
Changing MachineKey
<machineKey validationKey="32E35872597989D14CC1D5D9F5B1E94238D0EE32CF10AA2D2059533DF6035F4F" decryptionKey="B179091DBB2389B996A526DE8BCD7ACFDBCAB04EF1D085481C61496F693DF5F4"
validation="MD5" decryption="Auto" />
If I do that, I get the follow error in #Html.AntiForgeryToken():
**ConfigurationErrorsException was unhandled...**
When using <machineKey compatibilityMode="Framework45" /> or the MachineKey.Protect and MachineKey.Unprotect APIs,
the 'validation' attribute must be one of these values: SHA1, HMACSHA256, HMACSHA384, HMACSHA512, or alg:[KeyedHashAlgorithm].
I need to write custom code to Encrypt/Decrypt MD5 in case MembershipPasswordFormat.Encrypted: or what I need to do, thanks.
This blog explains much better:
Opting in or out of the 4.5 code paths
As you might imagine, such drastic changes to the crypto pipeline come at the expense of compatibility. And since .NET 4.5 is an in-place update to .NET 4, we cannot enable these new behaviors by default, otherwise we run the unacceptable risk of breaking existing applications.
To opt in to the new ASP.NET 4.5 behaviors, all that need be done is to set the following in Web.config:
<machineKey compatibilityMode="Framework45" />
Alternatively, you can set the following switch, which is what the ASP.NET 4.5 project templates do:
The above switch is responsible for a slew of runtime behavioral changes, but that is a blog post for another day. The important bit here is that setting the target framework to 4.5 in the element automatically implies a default setting of Framework45 for the compatibility mode unless the machine key compatibility mode has been explicitly specified.
ASP.NET has historically supported sharing forms authentication tickets between different versions of the framework. This allows tickets to be generated by an application running ASP.NET 2.0 and validated by an application running ASP.NET 4, for example. If you are writing an application targeting ASP.NET 4.5 (you have set ) and you need to share tickets with applications running earlier versions of ASP.NET, you must set the following in the 4.5 project's Web.config:
The value Framework20SP1 is the default machine key compatibility mode for all ASP.NET versions. This has the effect of using the legacy crypto code paths, even if .NET 4.5 is installed on the machine. An existing ASP.NET 4 application that happens to be running on a machine with 4.5 installed will not get the new behaviors automatically since neither nor would be present in that application's Web.config. If, however, you have made a new application targeting 4.5 (and as such it has those config settings) and need to maintain forms authentication ticket compatibility with existing applications, you can set Framework20SP1 to be interoperable with earlier versions of ASP.NET
http://blogs.msdn.com/b/webdev/archive/2012/10/23/cryptographic-improvements-in-asp-net-4-5-pt-2.aspx
Try:
<machineKey compatibilityMode="Framework20SP2"....
NOTE: that's a lowercase "c" in compatibilityMode.
The possible values are for the compatibilityMode property are:
Framework20SP1,
Framework20SP2,
Framework45
See:
http://msdn.microsoft.com/en-us/library/system.web.configuration.machinekeysection.compatibilitymode(v=vs.110).aspx
Update your machine key tag to add the following (MSDN):
<machineKey compatibilityMode="Framework20SP1".... />
Note: the lowercase "c" in compatibilityMode
But seriously, MD5 is a very weak algorithm and if at all possible, get away from using it and use a more secure encryption scheme. This is one of the reasons it has been removed as a valid encryption algorithm in the newer .NET frameworks.

Glimpse throws NullReferenceException with EPiServer 7.1 MVC 4

I have an MVC 4 application built on top of EPiServer 7.1. EPiServer uses StructureMap as it's IoC framework, which may be related to my problems. Anyhow, this is what I have done:
Via "Manage Nuget Packages...", added "Glimpse Mvc4" to my project
Verified that web.config was updated as expected
Restarted my application
After adding Glimpse, all requests fail with a NullReferenceException, e.g., like this:
I have tried enabling Glimpse logging by commenting in 'logging level="Trace"' in the Glimpse-section of web.config, but can't find any logging in neither Windows event logs or log4net log files.
Ideas on how to troubleshoot further, or hints to a solution?
A workaround (thanks to #avanderhoorn!) is to add this to the "glimpse" section of web.config:
<glimpse defaultRuntimePolicy="On" endpointBaseUri="~/Glimpse.axd">
<tabs>
<ignoredTypes>
<add type="Glimpse.AspNet.Tab.Routes, Glimpse.AspNet"/>
</ignoredTypes>
</tabs>
<inspectors>
<ignoredTypes>
<add type="Glimpse.AspNet.Inspector.RoutesInspector, Glimpse.AspNet"/>
<add type="Glimpse.Mvc.Inspector.ModelBinderInspector, Glimpse.Mvc4"/>
</ignoredTypes>
</inspectors>
</glimpse>
This disables the two parts of Glimpse that break with EPiServer. As far as I can see, you still get the most useful parts available!
+1 the same here. What I found so far is that by adding Glimpse it augments all routes and replaces with it's own proxy classes for intercepting calls to routing.
EPiServer (and UrlResolver in particular) seems that don't like this case. The root cause for this exception is following method:
UrlResolver.GetVirtualPath(ContentReference contentLink, string language, RouteValueDictionary routeValues, RequestContext requestContext)
What it doesn't like is fact that there is no route of type ContentRoute in the routing table:
foreach (RouteBase base2 in from r in this._routes
where (bool) (r is ContentRoute)
select r)
{
...
if(...)
{
return virtualPath;
}
}
return null;
And after returning null to the caller NullReferenceExpcetion occours in:
UrlExtensions.MapUrlFromRoute(RequestContext requestContext, RouteCollection routeCollection, string url)
Seems like patch from EPiServer should be awaited.

mini profiler WCF

I am trying to use mini profiler with WCF.
I keep getting a 404 error:
http://website/mini-profiler-resources/results
There are no results being returned.
I am using two versions of the mini profiler. The NUGET version which doesn't include support for WCF works just fine.
I downloaded the git version so that I can use the WCF integration.
I note that if I run the test project included in the sources 'Sample.Mvc' the same error occurs when the home page is executed, but not for some of the links. I cannot seem to get results for any of my own web site pages. The same 404 occurs.
I have downloaded the master version. I am using .NET 4.0 and studio 2010.
I have the following in the config file, I have tried with and without the handlers.
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true" />
<handlers>
<add name="MiniProfiler" path="mini-profiler-resources/*" verb="*" type="System.Web.Routing.UrlRoutingModule" resourceType="Unspecified" preCondition="integratedMode" />
</handlers>
</system.webServer>
I am definitely calling the start and stop methods.
StackExchange.Profiling.MiniProfiler.Stop();
I have read this: MvcMiniProfiler results request giving 404 in Asp.Net MVC app
It did not help.
I have found a clue as to the problem
The following code in miniprofiler is returning NotFound
The profiler is expecting some kind of guid value to be present, and it isn't.
private static string Results(HttpContext context) {
// this guid is the MiniProfiler.Id property
Guid id;
if (!Guid.TryParse(context.Request["id"], out id))
return isPopup ? NotFound(context) : NotFound(context, "text/plain", "No Guid id specified on the query string");
temporary fix
I took out the code above, and just collected the first guid out of storage, and this fixed the problem. I think this code needs cleaning up. I need to learn GIT, and then try and clean it up myself.
var id = MiniProfiler.Settings.Storage.List(10).FirstOrDefault();
Can you see .../mini-profiler-resources/results-index ?
Handler not required btw. There is a comma in your link but assume that is just a question typo.
Are you calling start last thing in the Application_BeginRequest() and stop in Application_EndRequest()
Have you set GlobalFilters.Filters.Add(new ProfilingActionFilter());?
and are you using WebActivator with a MiniProfilerPackage and MiniProfilerStartupModule
Think I need to tidy up my own implementation as looks like I have some unnecessary cruft.