Website Deployment

...now browsing by category

 

Unexpected consequence of Environment Variable change

Saturday, April 16th, 2016

While working on an Azure-bounded .Net project today, I ran into some error that required me to shorten the temp folder path. So I went ahead and changed the default user environment variable value from %USERPROFILE%\AppData\Local\Temp to C:\App\Temp. But before I made the change, I forgot to create the physical path C:\App\Temp first; not sure this is a Windows 10 bug – when I saved the change, the system environment variable editor just let me do it without checking if the path already existed. I strongly believe this should be part of Windows Environment Variables Editor’s enhanced feature to stop user from saving if the path does not exist.

This small omission turned out to be a huge problem – since the temp folder path: C:\App\Temp did not actually exist, it led to all kinds of weird behaviors as listed below:

  • My Visual Studio 2015 would not compile any project
  • My OneNote 2016 suddenly stopped working
  • When I tried to re-install VS 2015 or any program, it would just go into limbo – nothing happened
  • And I could not uninstall any program from the Programs list.
  • All these strange and frustrated Windows behaviors logged no errors into the Event Log so there was no much to go about and find answers by Google search.

Sure, I knew all these bad things were caused by the change of Temp file path, so I quickly restored the original settings – but that did not make these weirdness disappear.

While I was almost at the point to submit a HelpDesk ticket to have IT rebuild my machine, my director came to rescue – he suggested I change the Temp file path again to something like C:\Temp but this time we made sure I create the folder C:\Temp first. Well, after that and a reboot of my machine, everything came back normal and functional as expected.

So, two things worth shouting out loud:

  • Never never change the Windows Environment Variable to point to a path that has not been created yet.
  • For Windows 10 developer, PLEASE PLEASE include some Path.Exist() checking to prevent user from saving the change if the path does not exist yet. Such a simple feature enhancement could play a huge role in enlightening one’s Windows life.

 

 

Simplified process of creating and publishing nuget package to local host

Monday, March 9th, 2015

The simplified steps to pack and publish nuget packages to local host:

Add NuGet executable path to system variables:

  • Opened Properties page of Computer and click on Advanced System Settings and select Environment Variables
  • Highlight the Path under System Variables and click on Edit
  • Located the folder where the Nuget.exe is located, in this case, C:\Program Files (x86)\NuGet\Visual Studio 2012 and add this path to the Variable value – separated by semi-colon;
  • Need to re-start the computer in order for this to take effect.

 Package the libraries that are to be published to the server:

    • Launch the Developer Command Prompt for VS2012 and browse to the folder where the project file is located; in this case G:\Development\Tryout\NugetServer\Demo.Nuget.Lib>
    • Run command nuget spec to create the .nuspec file first:
      G:\Development\Tryout\NugetServer\Demo.Nuget.Lib>nuget spec -f Demo.Nuget.Lib.cs
      proj
      Created 'Demo.Nuget.Lib.nuspec' successfully.
      

      use -f to force overwrite if the .nuspec file already exists.

    • Open the .nuspec file and remove these entries from the file for now:
       <licenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
       <projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
       <iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
      <tags>Tag1 Tag2</tags>
      
      
      

      and make sure also change the text of releaseNotes to something other than the default; if you don’t to this, you will get an annoying warning message asking you to change.

    • Then run nuget pack command:
      G:\Development\Tryout\NugetServer\Demo.Nuget.Lib>nuget pack Demo.Nuget.Lib.cspro
      j -includeReferencedProjects
      Attempting to build package from 'Demo.Nuget.Lib.csproj'.
      Packing files from 'G:\Development\Tryout\NugetServer\Demo.Nuget.Lib\bin\Debug'.
      
      Using 'Demo.Nuget.Lib.nuspec' for metadata.
      Successfully created package 'G:\Development\Tryout\NugetServer\Demo.Nuget.Lib\D
      emo.Nuget.Lib.1.0.0.2.nupkg'.
      
      G:\Development\Tryout\NugetServer\Demo.Nuget.Lib>
      
      

Publish the package to local server:

      • Finally, do a push to publish to localhost:
        G:\Development\Tryout\NugetServer\Demo.Nuget.Lib>nuget push Demo.Nuget.Lib.1.0.0
        .2.nupkg -s http://localhost:{portnumber if not default 80, for example 8090 was what I used} {api key this has to be obtained from Nuget.org}
        Pushing Demo.Nuget.Lib 1.0.0.2 to 'http://localhost:8099'...
        Your package was pushed.
        
        
      • The local server was previously setup by following this article at https://docs.nuget.org/create/hosting-your-own-nuget-feeds

Consume the packages from the local Nuget Server:

Now that the package are published to the local server, here are the steps to consume it from inside a Visual Studio 2012 solution:

  • Added a Console project “Demo.Nuget.Consumer”
  • Go to Tools->Nuget Package Manager->Manager Nuget Packages for Solution
  • Click on Setting on the lower left corner and select Package Sources under the Package Manager from the Options pane on the left; click on the “+” sign to add a new package source
  • Type in the Source text box the local Nuget server url that was used in the publishing process, and add nuget at the end, for example in this case :http://localhost:8099/nuget
  • Once the Package source is added, then all the .nupkg files in the Packages folder on the server will be displayed on the “Manage NuGet Packages” screen and ready to be installed to the solution.
  • To make more packed assemblies to be available to the source, just simply copy the desired .nupkg file(s) to the Packages folder on the server and they will automatically show up for your solution.

 

How to connect to BizTalk Management database (BizTalkMgmtDb) via BizTalk API?

Friday, September 12th, 2014

When calling Microsoft.BizTalk.ExplorerOM.BtsCatalogExplorer.ConnectionString and assigned it a connection string like
“Data Source=sqlservernameorIP;initial catalog=BizTalkMgmtDb;user id=userid;password=pwd;” providerName=”System.Data.SqlClient”

I would get an error even I know the credential is correct and the SQL Server is setup with Mixed mode so it will take both SQL server authentication and Windows Authentication:
Login failed. The login is from an untrusted domain and cannot be used with Windows authentication.

With the same user credential, I can connect to other database on the same server if I don’t use BizTalk API call. That indicates that the BizTalk API only accept Windows authenticated domain user account.

Then, how will I pass a domain user account through web?
1) Go to IIS where the web application is hosed.
2) Select the ApplicationPool for the app and click on Advanced Settings
3) Select Identity and change it to use Custom Account (from Built in Account). Click on Set and enter a domain account; you must enter the domain name such as TGIF\syang; this domain account must exist and must have proper access to the server where the BizTalk database resides.
4) If the domain account has not been given proper access to the BizTalkMgmtDb, now it is time to go to the database server, expand the Security folder then select the Logins. Add TGIF\syang to Logins as new user if it is not already there.
5) Then you must make sure the user is mapped to the database with proper role. This is done by clicking on User Mapping page after you bring up the user’s Properties. Select the BizTalkMgmtDb database by checking the Map box, then in the “Database role membership” window below, check BTS_Admin_Users.

Then, is it true that the connection string with a sql server user account no longer needed?
No, it is still needed. After I made the changes in IIS and was able to connect to the BizTalk Explorer, I intentionally passed in an invalid userid to the sql server connection string as in [“”Data Source=sqlservernameorIP;initial catalog=BizTalkMgmtDb;user id=userid;password=pwd;” providerName=”System.Data.SqlClient”], immediately, I got an error from BizTalk API call where it initializes the connection to BizTalkMgmtDb.

So, in summary, BizTalk Explorer API requires:
1) An authenticated and authorized Windows domain account to access its management database (where information like Receive Locations, Ports, etc reside)
2)If the application is a web application hosted in IIS, IIS Application Pool must be setup using Custom Account instead of the default Built-in Account
3)When passing in a SQL server connection string, this connection must be set to use Integrated Security or SQL server authentication with a user that is grant proper access. If using SQL Server authentication, steps 1 and 2) are still needed.

Manually added Elmah to a deployed Asp.Net website

Tuesday, June 18th, 2013

Sometimes I found that it was frustrating to not know what exception detail was when an exception was thrown from a production website. At that point, the all-mighty Elmah error logging and exception handling plug-in came to my mind. But all my previous Elmah plug-in was added during web project development and deployed along with the project to hosting server. How to go about plugging in an Elmah when my website is already up there and running? Here were the steps I went through the other day to accomplish exactly that:

  1. Downloaded the elmah sql script file from https://code.google.com/p/elmah/downloads/detail?name=ELMAH-1.2-db-SQLServer.sql&can=2&q= and executed it against the sql database ProdDB on the host. It went through and created the Elmah_Error table and related stored procs inside ProdDB database
  2. Now let’s manually add elmah.dll and configure the web.config to register elmah.
  3. Copied elmah.dll from one of my old projects that had Elmah already working to the target bin folder.
  4. Added to <configuration><configSections> the following:
    <sectionGroup name="elmah"><section name="security" type="Elmah.SecuritySectionHandler, Elmah" />
    <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
    <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" /></sectionGroup>
  5. Added to <httpHandlers>:
    <add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah"/>
  6. Added to <httpModules>:
    <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
    <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" />
    <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" />
  7. Added <elmah> to <configuration> right after </system.web> and before <system.net>
    <elmah>
    <!--<errorLog type="Elmah.XmlFileErrorLog, Elmah" logPath="~/App_Data/Errors" />-->
    <errorLog applicationName="AppName" connectionStringName="connToProdDb" type="Elmah.SqlErrorLog, Elmah" />
    <errorMail subject="Website error via Elmah" to="stevey@yangsoft.com" from="webmaster@yangsoft.com" aysnc="true" />
    
    <security allowRemoteAccess="no" />
    
    </elmah>
  8. Last, but not least, in order to get the alert email sent out automatically to me, I needed to add the SMTP parameters to the mailSettings section in the <system.net>
    <mailSettings>
    <smtp deliveryMethod="Network">
    <network host="mail.domainname.com" userName="webmaster@domainname.com" password="password" port="numberthatworks" />
    
    </smtp>
    
    </mailSettings>

    (there was no <system.net>, so just created one)

  9. Added the following right after </system.net> and before <system.webserver>
    <!--deny annonymous access to error log-->
    <location path="elmah.axd">
    <system.web>
    
    <authorization>
    <allow users="*"/>
    <!--<deny users="?" />-->
    </authorization>
    </system.web>
    
    </location>
  10. Added to <system.webserver><modules>:
    <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
    <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" />
    <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" />
  11. Added to <system.webserver><handlers>
    <add name="Elmah" path="elmah.axd" verb="POST,GET,HEAD" type="Elmah.ErrorLogPageFactory, Elmah" preCondition="integratedMode" />
  12. Finally, it is completed! Now browsed to the site and manually generated some errors; immediately, I got an email alert; then I browsed to the elmah.axd, and it also rendered all the errors in a tabulated format nice and neat. Of course, more detail info is obtained by clicking on the detail link and you will be surprised how much exception stack trace has been caught.

ASP.NET Web service call error, “Unable to generate a temporary class (result=1)”

Tuesday, February 19th, 2013

Got this obscure error while calling a web service method that requires a Xml serializer:

Unable to generate a temporary class (result=1).\r\nerror CS2001: Source file ‘C:\\Windows\\TEMP\\qdrb02m1.0.cs’ could not be found\r\nerror CS2008: No inputs specified\r\n”}  System.Exception {System.InvalidOperationException} “

 

Web searches on key phrase “Unable to generate a temporary class (result=1)” returned some useful results but none could directly resolve my issue. But general direction was pointing to the proper permission of the ASP.Net surrogate identity that most likely does not have sufficient right to the local I/O where XML serialization takes place.

To prove this, I fired up a console application and called the same web service method; as anticipated, the Console app did not throw error at all. So that’s true – it is to do with the Windows account that IIS uses to run the ASP.Net process.

By default, IIS7 uses “ApplicationPoolIdentity” as the Identity for the Application pool automatically created when a new website is added to the IIS/Sites. But what’s underneath this mysterious “ApplicationPoolIdentity” – you could not even find it in Windows by looking up user accounts? Below are several things I tried and let’s see how they fared:

  1. I tried to give “Full Control” permission to ASP.NET Machine Account on c:\windows\Temp folder. Not work.
  2. Changed the app pool identity to “Network Service” (via IIS7/Site/Advanced Settings) and gave the “Network Service” full control permission to c:\windows\temp (via Windows Explorer). It worked! Then I reduced permission to only “Read, List Folder Contents”, and it still worked.
  3. Changed the app pool identity to “Local System”, of course that worked too.

 

So, at the end, to get rid of error “Unable to generate a temporary class (result=1)..”,  I ended up using the “Network Service” as the Application Pool identity (leave the security mode as Integrated) and granted the “Network Service” account permission “Read, List folder contents” on “C:\Windows\Temp” folder.

P.S.: after I deployed the web app to my staging web server, the error returned. The staging server is running IIS6 and the app pool identity by default was already tied to “Network Service” account. So I went directly to the c:\windows\temp folder and as I anticipated, the account did not have “read, list folder contents” permission. So I granted the permission to “Network Service” account and then it all worked!

Installed WordPresss to Local IIS7

Monday, February 13th, 2012

Before my memory evaporates again, let’s write down the steps on how this was done:

  1. Downloaded and Installed MySql database engine, then the Workbench (acts like SQL Server Management Studio). No need to write down the version; you will always to go their site to get the latest.
  2. I already installed PHP engine the other day so no need to redo it; this time around, just go to WordPress site http://www.wordpress.org and grabbed the latest .zip file, expanded to D:\Download\Wordpress
  3. Went to IIS7 Manager and added a new site, called “wordpress” and set the physical path to d:\download\wordpress, let the site use default ApplicationPool Identity, wordpress; and set binding to port 8089 and host name “blog.yang.com”.
  4. Before I could browse to http://blog.yang.com:8089, I needed to update the local host file; to do so, browsed to c:\windows\system32\drivers\etc\hosts. The file was not editable by default; so I opened the file property and gave myself  full control permission, changed the entry there from 127.0.0.1 blog.yangsoft.com to blog.yang.com; if the entry is not there, just add one.
  5. Before I could run wp install, I needed to create a database on local mysql server. I launched MySQL WorkBench 5.2 CE ->Server Administration ->File -> New Model. Once I clicked on New Model from File menu, it automatically created a MyDB, clicked on Edit schema and changed name to myblog, selecting collation to be UTF8-UTF8_General_CI.
  6. Added a mysql user account and gave it full db rights.
  7. It is almost there. Now I went to d:\download\wordpress and opened wp-config-sample.php, replaced DB related settings to point to localhost, db name “myblog” and the newly created username. Now I was ready to run WP install, the famous 5 minutes no-brainer!
  8. Went to IIS7, browsed to wordpress/wp-admin/install.php, and it was truly amazing it did only take about 5 minutes to get the site up and running!

How to move your SQL server database from one hosting site to another

Sunday, February 5th, 2012

I normally used backup and restore tool in SQL server to move one sql server database to another server in the same network; but this does not work if your db is in a remote shared hosting site like Godaddy. To get my sql db from Godaddy shared hosting environment and move it to local sql server or a different host server, I had to use Microsoft Database Publishing Wizard. This evening I have downloaded my sql server db (called it remoteDB) to my local sql 2008 express successfully, by going through these steps:

  1. Open a VS2010 Project (existing or create a new).
  2. Go to Server Explorer ->Data Connections, right click and select “Add New Connection”.
  3. Enter remotedb.db.xxxx.godaddyresource.com to “Server Name” and select “use SQL server authentication”; enter username and password assigned by Godaddy for the database.
  4. If server name, and user credential are correct and validated, your target database will now display under the “Select or enter a database name” dropdown box.
  5. Select the database and press OK.
  6. Return to Database Connections, right click on the newly added data connection, select “Publish to Provider” from the context menu.
  7. The Microsoft Database Publishing Wizard appears; just follow the onscreen instruction to script out all database objects for the selected database.
  8. When asked to “Select an Output Location”, I selected “Script to file” and saved to a sql file at local drive. “c:\development\remote\db\sqlbackup\remotedb_published_2-5-12.sql”.
  9. when asked to “Select Publishing Options”, I selected:
    • Drop existing objects in script =True
    • Schema qualify =True
    • Script for target database =SQL Server 2008 (other options are 2005 and 2000)
    • Type of data to publish=Schema and data
  10. Click on Finish.
  11. Now, open the localhost\SQLExpress2008 and attached the remoreDb.mdf from an older version
  12. Open the .sql file “remotedb_published_2-5-12.sql” and executed the sql file
  13. Verified all data and objects were imported as current as of 2-3-2012.

If publishing to another remote sql server, you will use SQL Server 2008 Management Studio to connect to that remote database, and execute the sql file directly against that database.

Deploy .Net 4.0 Website to Local IIS7

Wednesday, January 18th, 2012

I had a website that was upgraded from .Net 2.0 to v.4.0; normally I used Web Deployment Project to pack it and deploy to remote IIS6 server using xcopy and had not encountered the need to deploy to local IIS which is IIS7 now. Today I did, and ran into a few errors before getting it to run, so I recorded the steps and fixes here to refresh myself and help others from being hassled by these again:

  1. Used Web Deployment Project to deploy the solution (Output Assemblies setting: Merge all outputs to a single assembly and Treat as library component checked)
  2. I did not check the “Create an IIS virtual directory for the output folder option as I wanted to create the website manually.
  3. Opened IIS7 and added a new website, called it “NewAdmin”; went to binding and changed port to 8081 as other default ports were already taken by other sites; left the application pool to use the default one created by the system.
  4. By default every new site created in IIS7 uses ASP.Net v2.0, obviously, changed that to .Net v.4.xxxx, and left the Integrated mode and ApplicationPoolIdentity unchanged.
  5. Now browsed to the site and got this error, “There is a duplicate ‘system.web.extensions/scripting/scriptResourceHandler’ section defined”, and some more, “There is a duplicate ‘system.web.extensions/scripting/webServices/jsonSerialization’ section defined”..
  6. Googled and read postings from here, and led me to doing the next step
  7. Removed these sections from the sectionGroup:<section name=”scriptResourceHandler” type=”System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″ requirePermission=”false” allowDefinition=”MachineToApplication”/><section name=”jsonSerialization” type=”System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″ requirePermission=”false” allowDefinition=”Everywhere”/>
    <section name=”profileService” type=”System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″ requirePermission=”false” allowDefinition=”MachineToApplication”/>
    <section name=”authenticationService” type=”System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″ requirePermission=”false” allowDefinition=”MachineToApplication”/>
    <section name=”roleService” type=”System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″ requirePermission=”false” allowDefinition=”MachineToApplication”/>

     

  8. Browsed to the site again, a different error was displayed “The page you are requesting cannot be served because of the ISAPI and CGI Restriction list settings on the Web server.” what’s going on?
  9. Well, actually this should have been done in step 3) – I need to lift the ISAPI and CGI Restrictions on the site just created. By default, IIS7 shutdowns everything; this is far different from IIS6 and earlier version, so be aware!
  10. Went back to local host node, clicked on Features View, then double clicked on ISAPI and CGI Restrictions – saw that By default ASP.Net v4.0.30319 was restricted. Changed that to “Allow”.
  11. That’s it.