How to create an exe for a web application? - asp.net

I had developed a web application using Visual studio 2012 (ASP.Net 4.5 - C#) and a web service. Both are laying in a single solution. I need to convert my solution to an EXE file (Creating EXE for my web application). What i need exactly is, if run my setup file, it should host my web application and web service in IIS. Kindly provide the steps to solve me the problem.

Quiet a late answer:
I cannot post the whole project here but i'll post the flow chart here and you may try it.
All the steps in the flowchart here should be controlled programmatically.
1. Steps in starting the application.
NOTE: Please ignore the third layer (Is website added) if you are using a local database(.mdf)
The connection string to be used for a local database:
public string ConnectionString =
"Data Source=(local);Initial Catalog=YOUR_DATABASE_NAME;Integrated Security=True";
But still remember that you need dotnet framework to be installed inorder to run your application. don't worry as you can set the pre-requisites in your application setup project.
All the codes for the flowchart process below.
Is IIS Installed:
NOTE: I am posting the code for IIS 7 and above.
public bool IsIISInstalled()
{
return Registry.GetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\InetStp",
"VersionString", null) != null;
}
Install IIS
public int InstallIIS()
{
string DISM_CMD_CODE = "START /WAIT DISM /Online /Enable-Feature /FeatureName:IIS-ApplicationDevelopment /FeatureName:IIS-ASP /FeatureName:IIS-ASPNET /FeatureName:IIS-BasicAuthentication /FeatureName:IIS-CGI /FeatureName:IIS-ClientCertificateMappingAuthentication /FeatureName:IIS-CommonHttpFeatures /FeatureName:IIS-CustomLogging /FeatureName:IIS-DefaultDocument /FeatureName:IIS-DigestAuthentication /FeatureName:IIS-DirectoryBrowsing /FeatureName:IIS-FTPExtensibility /FeatureName:IIS-FTPServer /FeatureName:IIS-FTPSvc /FeatureName:IIS-HealthAndDiagnostics /FeatureName:IIS-HostableWebCore /FeatureName:IIS-HttpCompressionDynamic /FeatureName:IIS-HttpCompressionStatic /FeatureName:IIS-HttpErrors /FeatureName:IIS-HttpLogging /FeatureName:IIS-HttpRedirect /FeatureName:IIS-HttpTracing /FeatureName:IIS-IIS6ManagementCompatibility /FeatureName:IIS-IISCertificateMappingAuthentication /FeatureName:IIS-IPSecurity /FeatureName:IIS-ISAPIExtensions /FeatureName:IIS-ISAPIFilter /FeatureName:IIS-LegacyScripts /FeatureName:IIS-LegacySnapIn /FeatureName:IIS-LoggingLibraries /FeatureName:IIS-ManagementConsole /FeatureName:IIS-ManagementScriptingTools /FeatureName:IIS-ManagementService /FeatureName:IIS-Metabase /FeatureName:IIS-NetFxExtensibility /FeatureName:IIS-ODBCLogging /FeatureName:IIS-Performance /FeatureName:IIS-RequestFiltering /FeatureName:IIS-RequestMonitor /FeatureName:IIS-Security /FeatureName:IIS-ServerSideIncludes /FeatureName:IIS-StaticContent /FeatureName:IIS-URLAuthorization /FeatureName:IIS-WebDAV /FeatureName:IIS-WebServer /FeatureName:IIS-WebServerManagementTools /FeatureName:IIS-WebServerRole /FeatureName:IIS-WindowsAuthentication /FeatureName:IIS-WMICompatibility /FeatureName:WAS-ConfigurationAPI /FeatureName:WAS-NetFxEnvironment /FeatureName:WAS-ProcessModel /FeatureName:WAS-WindowsActivationService";
string command = DISM_CMD_CODE;
ProcessStartInfo pStartInfo = new ProcessStartInfo("cmd.exe", "/c " + command);
Process p = new Process();
p.StartInfo = pStartInfo;
//p.WaitForExit();
p.Start();
return 1;
}
Is Website added
public bool IsWebsiteAddedInIIS(string WebsiteName)
{
ServerManager serverManager = new ServerManager();
var site = serverManager.Sites.FirstOrDefault(s => s.Name == WebsiteName);
if (site == null)
{
//No site added
return false;
}
else
{
//site added
return true;
}
}
public int CreateNewWebsite(string SiteName, string PublishedFilesPath)
{
ServerManager serverManager = new ServerManager();
var site = serverManager.Sites.FirstOrDefault(s => s.Name == SiteName);
if (site == null)
{
serverManager.Sites.Add(SiteName, "http", "*:8080:", PublishedFilesPath);
serverManager.CommitChanges();
return 1;
}
else
{
return 2;
}
}
public void StartWebsite(string SiteName)
{
ServerManager serverManager = new ServerManager();
var site = serverManager.Sites.FirstOrDefault(s => s.Name == SiteName);
if (site != null)
{
site.Stop();
site.Start();
}
}
public void StopWebsite(string SiteName)
{
ServerManager serverManager = new ServerManager();
var site = serverManager.Sites.FirstOrDefault(s => s.Name == SiteName);
if (site != null)
{
site.Stop();
}
}
Get website URL
public string GetWebsiteURL(string SiteName)
{
//string SiteUrl = "";
//ServerManager serverManager = new ServerManager();
//var site = serverManager.Sites.FirstOrDefault(s => s.Name == SiteName);
//var siteBindings = site.GetCollection("bindings");
//string protocol = (string)siteBindings["protocol"];
//string bindingInfo = (string)siteBindings["bindingInformation"];
//if (protocol.StartsWith("http", StringComparison.OrdinalIgnoreCase))
//{
// string[] parts = bindingInfo.Split(':');
// if (parts.Length == 3)
// {
// //Get the port in use HERE !!!
// string port = parts[1];
// SiteUrl = "localhost:" + port;
// }
//}
//return SiteUrl;
int port = 0;
string SiteUrl = "";
ServerManager serverManager = new ServerManager();
var site = serverManager.Sites.FirstOrDefault(s => s.Name == SiteName);
foreach (Binding binding in site.Bindings)
{
port = binding.EndPoint.Port;
SiteUrl = "localhost:" + port + "/index.aspx";
break;
}
return SiteUrl;
}
Init Browsing the website
You have to install Cefsharp chromium browser to your windows forms
Install-Package CefSharp.WinForms -Version 75.1.143
public void InitBrowser(string Address)
{
Cef.Initialize(new CefSettings());
browser = new ChromiumWebBrowser(Address);
Controls.Add(browser);
browser.Dock = DockStyle.Fill;
}
Thank you..

Maybe you need to create a web setup project. "A Web setup project provides the
highest level of flexibility for deploying a website. Although Web Setup Projects are more
complex for the developer, they allow you to generate an MSI package, precompile a website,
and perform virtually any setup task that your application might require.
Many websites do not require custom configuration. In these cases, you can simply build
your MSI file and be ready to deploy. However, more complex scenarios include dependencies
(such as particular operating system versions or service packs), custom registry entries,
or administrator configuration. Web Setup Projects allow you to deploy websites that meet
these requirements."
Check the book "MCTS Self-Paced Training Kit (Exam 70-515) - Web Applications Development with Microsoft .NET Framework 4" at the chapter 8 "Debugging and deploying".
Hope this helps.

Related

EPPLUS package works fine locally but returns Internal server error when deployed to azure server

I have my web api that uploads and reads an excel file from the client app and then afterwards saves the data into the database, the application works perfect on locally server but the problem comes when the application is deployed to azure server it returns error 500 internal server error therefore i don't understand why this happens and and don't know how i can track to understand what might be the cause below are my code blocks.
My Interface Class
public interface UploadExcelInterface
{
Task UploadMultipleClients(Client obj);
}
My Service Implementation
public class UploadExcelService : UploadExcelInterface
{
private readonly DbContext _connect;
private readonly IHttpContextAccessor httpContextAccessor;
public UploadExcelService(DbContext _connect, IHttpContextAccessor httpContextAccessor)
{
this._connect = _connect;
this.httpContextAccessor = httpContextAccessor;
}
public async Task UploadMultipleClients(Client obj)
{
var file = httpContextAccessor.HttpContext.Request.Form.Files[0];
if (file != null && file.Length > 0)
{
var folderName = Path.Combine("Datas", "ClientUPloads");
var pathToSave = Path.Combine(Directory.GetCurrentDirectory(), folderName);
var fileName = Guid.NewGuid() + ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');
var fullPath = Path.Combine(pathToSave, fileName);
var clientsList = new List<Client>();
using (var fileStream = new FileStream(fullPath, FileMode.Create))
{
await file.CopyToAsync(fileStream);
FileInfo excelFile = new FileInfo(Path.Combine(pathToSave, fileName));
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
using (ExcelPackage package = new ExcelPackage(excelFile))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets[0];
var rowcount = worksheet.Dimension.Rows;
for (int row = 2; row <= rowcount; row++)
{
var Names = (worksheet.Cells[row,2].Value ?? string.Empty).ToString().Trim();
var Address = (worksheet.Cells[row,3].Value ?? string.Empty).ToString().Trim();
var Title = (worksheet.Cells[row,4].Value ?? string.Empty).ToString().Trim();
var Product = (worksheet.Cells[row,5].Value ?? string.Empty).ToString().Trim();
var Order = (worksheet.Cells[row,6].Value ?? string.Empty).ToString().Trim();
var Email = (worksheet.Cells[row,7].Value ?? string.Empty).ToString().Trim();
var Price = (worksheet.Cells[row,8].Value ?? string.Empty).ToString().Trim();
clientsList.Add(new Client
{
Names = Names,
Address = Address,
Title = Title,
Product = Product,
Order = Order,
Email = Email,
Price = Price,
}
}
//adding clients into the database
foreach (Client client in clientsList)
{
var exist = _connect.client.Any(x => x.Email == client.Email);
if (!exist)
{
await _connect.client.AddAsync(client);
}
}
await _connect.SaveChangesAsync();
}
}
}
My Controller Class
[HttpPost]
public async Task UploadMultipleClients([FromForm] Client obj)
{
await uploadExcelInterface.UploadMultipleClients(obj);
}
}
Please any help regarding this error that am getting from the server, and addition on that is it possible to get the data from the excel file without uploading it to server if yes how? because i tried adding the file to memory stream an reading it from memory but it appers not work, any suggestions thanks.
My answer may not help you solve the problem directly, but it can locate the error step by step. After we fix the error, we should be able to solve the problem in this thread.
Suggestions
Please make sure you have inclue EPPlus library in your deploy content.
Enabling ASP.NET Core stdout log (Windows Server)
Azure App Service - Configure Detailed Error Logging
Why
After tested, I am sure azure webapp can support EPPlus. For 500 error, as we don't have a more specific error message to refer to, we can't quickly locate the problem. Following the suggested method, you will surely see some useful information.
E.g:
The class library of EPPlus was not found.
Folders such as Datas are not created.
The database connection string, the test environment and the production environment may be different.
...

Crystal Report 2011 Login prompt in asp.net

We are using Crystal Reports 2011 & SQL Server 2008 (Windows 7 64 bit). Whenever I try to deploy the crystal reports in the IIS it is always prompting enter the database login information. I have tried the below options
Set the login information in the code
Set IIS app pool to LocalService
Nothing works. Here is the code
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ConfigureCrystalReports();
}
else
{
ReportDocument doc = Session["Report"] as ReportDocument;
SetLogon(doc);
CrystalReportViewer1.ReportSource = doc;
CrystalReportViewer1.RefreshReport();
}
}
private void ConfigureCrystalReports()
{
ReportDocument reportDoc;
if (!IsPostBack)
{
reportDoc = new ReportDocument();
reportDoc.Load(Server.MapPath("~/Sample.rpt"));
Session.Add("Report", reportDoc);
}
else
{
reportDoc = Session["Report"] as ReportDocument;
}
SetLogon(reportDoc);
CrystalReportViewer1.ReportSource = reportDoc;
CrystalReportViewer1.RefreshReport();
}
private void SetLogon(ReportDocument reportDoc)
{
var connectionInfo1 = new ConnectionInfo()
{
ServerName = #"ODBCDSN",
DatabaseName = "hrdw_old",
IntegratedSecurity = true
};
SetDBLogonForReport(connectionInfo1, reportDoc);
}
private void SetDBLogonForReport(ConnectionInfo connectionInfo1, ReportDocument reportDocument)
{
Tables tables = reportDocument.Database.Tables;
foreach (CrystalDecisions.CrystalReports.Engine.Table table in tables)
{
TableLogOnInfo tableLogonInfo = table.LogOnInfo;
tableLogonInfo.ConnectionInfo = connectionInfo1;
tableLogonInfo.ConnectionInfo.Type = ConnectionInfoType.SQL;
table.ApplyLogOnInfo(tableLogonInfo);
}
reportDocument.SetDatabaseLogon(connectionInfo1.UserID, connectionInfo1.Password);
}
}
Steps tried in IIS:
Application pool: ASP.NET 4.0 Default app pool
Also enabled Windows Authentication in IIS & disabled anonymous authentication.
Tried anonymous authentication only.
SQL Server has both windows and sql server authentication.
I will not be able to use dataset since the crystal reports will be developed by someone using command objects. It works perfectly good in the Visual studio 2010 environment. But doesnt work in IIS.
Am I missing something basic? Any help is appreciated.
Thanks
Shankar.
Here is how this was solved. It was a bit of workaround
CrystalDecisions.ReportAppServer.ClientDoc.ISCDReportClientDocument rptClientDoc = doc.ReportClientDocument;
CrystalDecisions.ReportAppServer.ClientDoc.ISCDReportClientDocument rcd = rptClientDoc;
string server = #"<SERVER>";
string db = "<DATABASE>";
string user = "<USER>";
string pass = "PASSWORD";
rptClientDoc.DatabaseController.LogonEx(server, db, user, pass);
//Create the logon propertybag for the connection we wish to use
CrystalDecisions.ReportAppServer.DataDefModel.PropertyBag logonDetails = new CrystalDecisions.ReportAppServer.DataDefModel.PropertyBag();
logonDetails.Add("Auto Translate", -1);
logonDetails.Add("Connect Timeout", 15);
logonDetails.Add("Data Source", server);
logonDetails.Add("General Timeout", 0);
logonDetails.Add("Initial Catalog", db);
logonDetails.Add("Integrated Security", "false");
logonDetails.Add("Locale Identifier", 1033);
logonDetails.Add("OLE DB Services", -5);
logonDetails.Add("Provider", "SQLOLEDB");
logonDetails.Add("Use Encryption for Data", 0);
//Create the QE (query engine) propertybag with the provider details and logon property bag.
CrystalDecisions.ReportAppServer.DataDefModel.PropertyBag QE_Details = new CrystalDecisions.ReportAppServer.DataDefModel.PropertyBag();
QE_Details.Add("Database DLL", "crdb_ado.dll");
QE_Details.Add("QE_DatabaseName", db);
QE_Details.Add("QE_DatabaseType", "OLE DB (ADO)");
QE_Details.Add("QE_LogonProperties", logonDetails);
QE_Details.Add("QE_ServerDescription", server);
QE_Details.Add("QE_SQLDB", "True");
QE_Details.Add("SSO Enabled", "False");
CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo newConnInfo = new CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo();
CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfo oldConnInfo;
CrystalDecisions.ReportAppServer.DataDefModel.ConnectionInfos oldConnInfos;
oldConnInfos = rcd.DatabaseController.GetConnectionInfos(null);
for (int I = 0; I < oldConnInfos.Count; I++)
{
oldConnInfo = oldConnInfos[I];
newConnInfo.Attributes = QE_Details;
newConnInfo.Kind = CrystalDecisions.ReportAppServer.DataDefModel.CrConnectionInfoKindEnum.crConnectionInfoKindCRQE;
try
{
rcd.DatabaseController.ReplaceConnection(oldConnInfo, newConnInfo, null, CrystalDecisions.ReportAppServer.DataDefModel.CrDBOptionsEnum.crDBOptionDoNotVerifyDB);
}
catch (Exception ex)
{
Label1.Text = ex.Message;
return;
}
}
doc.SetDatabaseLogon(user, pass);
To ensure that there is no login prompt at all at first I had to login to the controller and then set all the login credentials. Ensure that login credentials are reused during post back as well. After this is done, login using the reportdocument as well. This solves the issue of login prompt coming again and again.
Thanks
Shankar

Win32_NetworkAdapterConfiguration with Non-administrative user (Access Denied)

I'm trying the change some configurations of the network adapters locally. I have to use a non-administrative user, but I just get the return value "91", which stands for "Access Denied", when I try to invoke methods. It was possible to set the rights for the "EnableStatic" method, but "SetDNSServerSearchOrder" doesn't work at all. It always returns "Access Denied". I cannot even disable the network adapter (in Win32_NetworkAdapter). Everything works great with an admin user. Since I had the same problem with "EnableStatic", I'm pretty sure, that there must be a way to get this working with the other methods. I set the security options in wmimgmt.msc for all namespaces, I set the limits in dcomcnfg, I granted permissions in the registry for tcpip, added the user in distributed com-users, performance groups, network configuration operators, but there is no way to get this working. I recognized, that there is no dns ip, when my tool was running. So something changes although the method is returning "Access Denied". Any ideas? Even Microsoft couldn't help me yet, since three weeks now. The tool is running without any problems, when I'm logged in as admin. Here is my C# Code: (and sorry for some mistakes in my written English ;) )
private static ManagementScope CreateScope(string strScope)
{
ManagementScope scope = new ManagementScope(strScope);
scope.Options.Impersonation = ImpersonationLevel.Impersonate;
scope.Options.Authentication = AuthenticationLevel.Packet;
return scope;
}
public static void SetIP(String strScope, String strQuery, string IPAddress, string SubnetMask, string Gateway, string DNSServer1, string DNSServer2)
{
ManagementScope scope = CreateScope(strScope);
SelectQuery query = new SelectQuery(strQuery);
Collection<object> objCol = new Collection<object>();
scope.Connect();
ManagementObjectCollection mobjCol = null;
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query))
{
mobjCol = searcher.Get();
}
foreach (ManagementObject objMO in mobjCol)
{
try
{
ManagementBaseObject objNewIP = null;
ManagementBaseObject objSetIP = null;
ManagementBaseObject objNewGate = null;
ManagementBaseObject objNewDNS = null;
objNewIP = objMO.GetMethodParameters("EnableStatic");
objNewGate = objMO.GetMethodParameters("SetGateways");
objNewDNS = objMO.GetMethodParameters("SetDNSServerSearchOrder");
//Set DefaultGateway
objNewGate["DefaultIPGateway"] = new string[] { Gateway };
objNewGate["GatewayCostMetric"] = new int[] { 1 };
//Set IPAddress and Subnet Mask
objNewIP["IPAddress"] = new string[] { IPAddress };
objNewIP["SubnetMask"] = new string[] { SubnetMask };
//Set DNS servers
objNewDNS["DNSServerSearchOrder"] = new string[] { DNSServer1, DNSServer2 };
//Invoke all changes
objSetIP = objMO.InvokeMethod("EnableStatic", objNewIP, null);
MessageBox.Show("EnableStatic: " + objSetIP["ReturnValue"].ToString());
objSetIP = objMO.InvokeMethod("SetGateways", objNewGate, null);
MessageBox.Show("SetGateways: " + objSetIP["ReturnValue"].ToString());
objSetIP = objMO.InvokeMethod("SetDNSServerSearchOrder", objNewDNS,null);
MessageBox.Show("SetDNSServerSearchOrder: " + objSetIP["ReturnValue"].ToString());
}
catch (ManagementException ex)
{
MessageBox.Show("Unable to Set IP : " + ex.Message);
}
}
}
non-administrative users need permissions to run WMI queries. You can set the relevant permissions using WMI Control [under ServerManager / Configuration or Computer Management / Services & Applications] ref: http://technet.microsoft.com/en-us/library/cc775497(v=ws.10).aspx
Try providing Execute Methods, Enable Account & Provider Write permissions to your non-admin user in the CIMV2 namespace.

ASP.NET Process Start PowerShell Script IIS 7.5

All works fine on my dev machine but if deployed to IIS the process doesn't get started. I am starting a powershell script by
private void RunScript()
{
Process process = null;
try
{
int timeout = 1800000;
var startInfo = new ProcessStartInfo
{
FileName = #"powershell.exe",
Arguments = string.Format("{0} {1}", "\path\toscript", "myParam"),
UseShellExecute = false,
CreateNoWindow = true
};
process = Process.Start(startInfo);
process.WaitForExit(timeout);
}
finally
{
if (!process.HasExited)
{
if (process.Responding)
process.CloseMainWindow();
else
process.Kill();
}
if (process != null)
{
process.Close();
process.Dispose();
}
}
}
Here's what's configured for the app pool this is running under.
Process Model
->Identity = domain user who is a Domain Admin.
->Load User Profile = True
Web App
Authentication is Windows
What else do I need to configure to so that I can run the Process?
As Start-Automating suggested I eventually ended up doing this:
using (Runspace runSpace = RunspaceFactory.CreateRunspace())
{
try
{
runSpace.Open();
RunspaceInvoke scriptInvoker = new RunspaceInvoke(runSpace);
scriptInvoker.Invoke("Set-ExecutionPolicy Unrestricted");
using (Pipeline pipeLine = runSpace.CreatePipeline())
{
var myCommand = new Command(scriptPath);
var myParam1 = new CommandParameter("-paramName", "someValue");
myCommand.Parameters.Add(myParam1);
pipeLine.Commands.Add(myCommand);
pipeLine.Commands.Add("Out-String");
Collection<PSObject> returnObjects = pipeLine.Invoke();
runSpace.Close();
return returnObjects;
}
}
finally
{
runSpace.Close();
}
}
On the IIS server I executed the following powershell command "Set-ExecutionPolicy RemoteSigned"
It's much better to embed the PowerShell APIs the call the .exe
Here's an old link that will get you a PowerShell runspace embedded in ASP.NET per user:
http://powershellpipeworks.com/
Check the permissions of the file system where powershell.exe lives.
Also, check the Security Log in the Event Viewer for authentication errors and access violations.

Web application creation in IIS7 via MS.Web.Admin

I am attempting to create seperate workflow instances as applications in IIS7 using the Microsoft.Web.Administration dll. When it attempts to add the Application to the Site ApplicationsCollection I get a COM error: "Invalid application path\r\n"
using (ServerManager manager = new ServerManager())
{
var site = manager.Sites.Where(x => x.Name == Properties.Settings.Default.WorkflowWebsiteName).Single();
StringBuilder stringBuilder = new StringBuilder()
.Append(m_workflowDefinition.AccountId)
.Append("/")
.Append(m_workflowDefinition.WorkflowDefinitionId)
.Append("/")
.Append(m_workflowDefinition.Version)
.Append("/");
string virtualPath = stringBuilder.ToString();
string physicalPath = Properties.Settings.Default.ApplicationPoolString +
virtualPath.Replace("/", "\\");
if (!Directory.Exists(physicalPath)) Directory.CreateDirectory(physicalPath);
//Create the workflow service definition file
using (StreamWriter writer = new StreamWriter(Path.Combine(physicalPath, m_workflowDefinition.WorkflowName + WORKFLOW_FILE_EXTENSION)))
{
writer.Write(m_workflowDefinition.Definition);
}
//Copy dependencies
string dependencyPath = m_workflowDefinition.DependenciesPath;
CopyAll(new DirectoryInfo(dependencyPath), new DirectoryInfo(physicalPath));
//Create a new IIS application for the workflow
var apps = site.Applications.Where(x => x.Path == virtualPath);
if (apps.Count() > 0)
{
site.Applications.Remove(apps.Single());
}
Application app = site.Applications.Add(virtualPath, physicalPath);
app.ApplicationPoolName = "Workflow AppPool";
app.EnabledProtocols = PROTOCOLS;
manager.CommitChanges();
}
The value assigned to virtualPath is like: "something/something/something" and for physicalPath it is "c:\inetpub\wwwroot\Workflow\something\something\something". Any ideas?
Any help is greatly appreciated.
Try changing your "something/something/something" path to "/something/something/something". The IIS administration call needs the extra slash at the beginning of the path.

Resources