Azure Cloud Service - Configure Session from RoleEnvironment - asp.net-mvc

Our application is hosted as a Cloud Service in Azure and we have all our connection strings and other connection-like settings defined in the ServiceConfiguration files. We are also using a Redis Cache as the session state store. We are trying to specify the Redis Cache host and access key in the ServiceConfig and then use those values for the deployment depending on where the bits land. The problem is session is defined in the web.config and we can't pull RoleEnvironment settings into the web.config.
We tried altering the web.config in the Application_Startup method but get errors that access is denied to the web.config on startup, which makes sense.
We don't really want to write deployment scripts to give the Network Service user access to the web.config.
Is there a way to setup session to use a different Redis Cache at runtime of the application?
The error that we are getting is "Access to the path 'E:\sitesroot\0\web.config' is denied'. I read an article that gave some examples on how to give the Network Service user access to the web.config as part of the role starting process and did that and then now we have access to the file but now get the following error "Unable to save config to file 'E:\sitesroot\0\web.config'."

We ended up being able to solve this using the ServerManager API in the WebRole.OnStart method. We did something like this:
using (var server = new ServerManager())
{
try
{
Site site = server.Sites[RoleEnvironment.CurrentRoleInstance.Id + "_Web"];
string physicalPath = site.Applications["/"].VirtualDirectories["/"].PhysicalPath;
string webConfigPath = Path.Combine(physicalPath, "web.config");
var doc = System.Xml.Linq.XDocument.Load(webConfigPath);
var redisCacheProviderSettings = doc.Descendants("sessionState").Single().Descendants("providers").Single().Descendants("add").Single();
redisCacheProviderSettings.SetAttributeValue("host", RoleEnvironment.GetConfigurationSettingValue("SessionRedisCacheHost"));
redisCacheProviderSettings.SetAttributeValue("accessKey", RoleEnvironment.GetConfigurationSettingValue("SessionRedisCacheAccessKey"));
redisCacheProviderSettings.SetAttributeValue("ssl", "true");
redisCacheProviderSettings.SetAttributeValue("throwOnError", "false");
doc.Save(webConfigPath);
}
catch (Exception ex)
{
// Log error
}
}

Related

How can I know if my app is running under Kestrel or HTTP.sys?

What's the best way to know if my app is running under Kestrel or HTTP.sys. All that I have found so far is to check for "Kestrel" in one of the HttpConext property class names.
Within an MVC controller I can do something like this:
Boolean IsKestrel = HttpContext.Features.GetType().ToString().Contains("Kestrel");
i.e. check this:
Features = {Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1Connection<Microsoft.AspNetCore.Hosting.HostingApplication.Context>}
When using HTTP.sys I only get:
Features = {Microsoft.AspNetCore.Http.Features.FeatureCollection}
(Is "Http" here enough to know that this is HTTP.sys?)
There must be a better way. Is there an obvious property somewhere that contains the name of the host being used?
A broader question might be, how do I know what the builder pattern built?
Update
Found something better, but still looking for a Property that has the server name or type.
In an MVC controller:
var isKestrel = HttpContext.Request.Headers.GetType().ToString().Contains(".Kestrel.");
var isHTTPsys = HttpContext.Request.Headers.GetType().ToString().Contains(".HttpSys.");
At the operating system level, netsh http show servicestate will list all active URLs listening via HTTP.SYS.
From code you can locate an instance of Microsoft.AspNetCore.Hosting.Server.IServer and check what its implementation is, in netcore 6:
Kestrel => Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl
IIS ==> Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer
HTTP.SYS => Microsoft.AspNetCore.Server.HttpSys.MessagePump
This relies on implementation details (so can break), also other extensions can change these e.g. CoreWcf creates CoreWCF.Configuration.WrappingIServer that wraps one of the above implementations.
you can use System.Diagnostics.Process.GetCurrentProcess().ProcessName
I am not sure whether you want to check this information using the code only or you are just looking for a way to know on which web server your app is running.
In my search result, I found that we could set the ports for a specific web server. When the application will run on that specific web server then it will use that pre-configured port. I am assuming your app also has a similar configuration. You could set the different ports for Kestrel, Http.sys, or IIS. By checking the port number you could say that on which web server your site is running.
You could try to go to the launchSettings.json file in your project where you could configure ports for IIS and Kestral.
Helpful References:
Kestrel Web Server in ASP.NET Core
Understand HTTP.sys Web Server In ASP.NET Core
Hello this is a good question, you question is asking how to find out from inside the code and not from a console.
OOB I did not find anything. So, I had to get very creative to figure this out, sorry for the typo's its brand new stuff...
Option 1:
Since the Kestrel section & endpoints are inside the appsettings.json I used that to find out if its hosted by Kestrel!
//Please create a static class to hold the config.
public static class MyStartupIsItKestrelConfiguration
{
public static IConfiguration Configuration;
public bool static IsKestrel()
{
//check your section kestrel??
var kestrel = configuration.GetSection("Kestrel");
// now check kestrel section or any other section
// see picture for kestrel endpoint in app setting sbelow
return true;
}
}
Now you can access it anywhere and see if you used Kestrel
//Now add it/save it in your startup and access later
public Startup(IConfiguration configuration)
{
Configuration = configuration;
MyStartupIsItKestrelConfiguration.Configuration = configuration;
}
Once you have this
//you can use it in ** YOUR CONTROLLER
MyStartupIsItKestrelConfiguration.IsKestrel();
Option 2:
Please check this public Microsoft.AspNetCore.Http.Features.IFeatureCollection Features { get; }
You can get the features public TFeature? Get<TFeature> (); as a Key Value Pair - and then check the feature for e.g. KESTREL DOES NOT ALLOW PORT SHARING
they split the features namespace in .net core 6 there are breaking changes
You should use the features collection

HttpContext.Current.Session gets cleared on routing in Azure Server

public static WebUser LoggedUser
{
get
{
WebUser sessionValue = null;
if (HttpContext.Current.Session["LoggedUser"] != null)
{
sessionValue = (WebUser)HttpContext.Current.Session["LoggedUser"];
}
return sessionValue;
}
set
{
HttpContext.Current.Session["LoggedUser"] = value;
}
}
HttpContext.Current.Session gets cleared on routing in Azure Server, the same works fine in IIS server but why not in Azure??
Please help me in persisting session value
HttpContext.Current.Session gets cleared on routing in Azure Server, the same works fine in IIS server but why not in Azure??
I assume that you use the multiple instances Azure WebApp. If it is that case, we could get the answer from the azure official document. Please have a try use external session state provider (either the Redis Cache Service or a SQL Server session state provider).
If your ASP.NET web app uses session state, you will need to configure an external session state provider (either the Redis Cache Service or a SQL Server session state provider). If you use session state, and don't use an external provider, you will be limited to one instance of your web app.

facing error while uploading file in mvc5 on server

I have MVC5 application , where I need to upload file excel and then then create data table of this excel. I use devexpress control to upload file. I use following code to store uploded file and then read in datatable and then store in database.
if (e.UploadedFile.IsValid)
{
e.UploadedFile.SaveAs(System.Web.HttpContext.Current.Server.MapPath("~/App_Data/" + e.UploadedFile.FileName));
var Filepath = System.IO.Path.Combine(System.Web.HttpContext.Current.Server.MapPath("~/App_Data/" + e.UploadedFile.FileName));
DataTable dtReport = new DataTable();
try
{
dtReport = CreateDataTableFromExcelFile(Filepath, "A1:U", true, "Sheet1").Tables[0];
}
catch
{
}
SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
con.Open();
System.Data.SqlClient.SqlBulkCopy sqlcopy = new System.Data.SqlClient.SqlBulkCopy(con);
sqlcopy.DestinationTableName = "table_Name";
sqlcopy.WriteToServer(dtReport);
con.Close();
If I host this application on IIS on my machine then it works fine. But If I host it on another server then it shows error
Access to the path 'C:\inetpub\wwwroot\MVC_Project_v3\App_Data\UploadTemp\dxupload_19aafa62643d42418b2fe5eaadede3cfcugxrc4e.nrt.tmp' is denied.
Please suggest right solution
The credential you are using to host the WebSite (the credential you enter in the application pool identity) does not have the privilege to access that directory.
Add a valid credential here.

Web Service client generated by wsdl not working with Deployed web service

I have generated a WSDL from a java class using axis2 java2wsdl utility as follows;
java2wsdl -o C:\temp -cn com.temenos.webservices.customer.CustomerServiceWS
Then I have deployed the same web service within an Application Server (say jBoss) in axis2 and I can browse the wsdl on http:// 127.0.0.1:8080/axis2/services/CustomerServiceWS?wsdl and call the methods on this service via standard client like SoapUI etc.
The problem is now that when I generated a client using standard java tooling 'wsimport' by providing a WSDL location as C:\temp (Generated WSDL from java2wsdl utility), my client is unable to communicate with the Deployed Web Service. I am using following code to access the web service;
// Initialise WS
CustomerServiceWS service = null;
CustomerServiceWSPortType servicePort = null;
try {
URL wsdlLocation = new URL("http://127.0.0.1:8080/axis2/services/CustomerServiceWS?wsdl");
QName serviceName = new QName("http://customer.webservices.temenos.com", "CustomerServiceWS");
service = new CustomerServiceWS(wsdlLocation, serviceName);
servicePort = service.getCustomerServiceWSHttpSoap12Endpoint();
} catch (MalformedURLException murle) {
murle.printStackTrace();
return;
}
But while creating an (service Port) Endpoint I am getting following error;
Exception in thread "main" javax.xml.ws.WebServiceException: An attempt was made to construct the ServiceDelegate object with an service name that is not valid: {http://customer.webservices.temenos.com}CustomerServiceWS.
at org.apache.axis2.jaxws.ExceptionFactory.createWebServiceException(ExceptionFactory.java:173)
at org.apache.axis2.jaxws.ExceptionFactory.makeWebServiceException(ExceptionFactory.java:70)
at org.apache.axis2.jaxws.ExceptionFactory.makeWebServiceException(ExceptionFactory.java:118)
at org.apache.axis2.jaxws.spi.ServiceDelegate.<init>(ServiceDelegate.java:218)
at org.apache.axis2.jaxws.spi.Provider.createServiceDelegate(Provider.java:59)
at javax.xml.ws.Service.<init>(Service.java:56)
at com.temenos.webservices.customer.CustomerServiceWS.<init>(CustomerServiceWS.java:42)
at com.temenos.services.customer.client.Client.testGetLanguage(Client.java:32)
at com.temenos.services.customer.client.Client.main(Client.java:21)
I have tried many things but it does not seems to like anything. Am I missing anything?
Thanks,
--
SJunejo
The problem was that I had axis2 in lib path because of that the call happend to org.apache.axis2.jaxws.spi.Provider.createServiceDelegate (Axi2 Provider) instead of Java WS Provider. I removed the axis2 libs from classpath and it seems to be working ok now. (though I am still unable to call my web service via client)
See the description of WSDL file and check the targetNamespace for the url to be given in QName(). Also import necessary packages.

Access to the path denied, trying to access remote server file

I'm having a hard time trying to access a remote server file from other server with my asp .Net application (C#) hosted in it. The scenario is the following:
I wrote an MVC web application that is hosted on SERVER A; and in some instance, it has to let the user modify a XML configuration file that is located on SERVER B. So, here is the part of the code where I try to read that file from a shared folder on SERVER B:
(C# - Controller)
WindowsImpersonationContext impContext = null;
try
{
impContext = NetworkSecurity.ImpersonateUser(
Settings.Default.ImpersonationDomain,
Settings.Default.ImpersonationUser,
Settings.Default.ImpersonationPass,
LogonType.LOGON32_LOGON_NETWORK,
LogonProvider.LOGON32_PROVIDER_DEFAULT);
}
catch (ApplicationException ex)
{
// write to log file
}
if (null != impContext)
{
try
{
//get the location of the configuration file
string remoteConfigFile = Settings.Default.RemoteDesktopMonitorCnfgFile;
//open the configuration file
XDocument xmlFile = XDocument.Load(#"\\SERVERB\Folder\configurationFile.exe.config");
So, my exception is here, when I try to open that configuration file, I'm getting the exception:
Access to the path '\\SERVERB\Folder\configurationFile.exe.config' is denied
As you could see, I'm impersonating the user before I try to read the file, that impersonation is well done; and I already gave full access to the shared resource to the user that I'm impersonating with. I even tryied joining that user to the Administrators group on both Servers (A and B) and the same exception occurs.
Maybe worth to say that both Servers are on the same Windows Domain, and that I'm using a user account that exists on the domain and that the password is correct.
Any help you could give me would be appreciate.
Thanks in advance.
There is a solution to your problem already on StackOverFlow
Check it out!

Resources