IIS, Programming, VB

Need To Clean Your IIS Log Files (Older Than x Number of Days) For All Sites? Here’s a Script

You may have the classic issue of needing logs cleared but you do not have time to log onto each server and delete files for space. Here’s a script that will do it for all IIS sites and will let you select how many days back you wish to keep. For this example this script is wrote for 30 days and would be run on a task scheduler monthly.

  • Open notepad and create a file called IISLogMonthlyCleanup.vbs
  • Put in the following snippet and adjust your settings to apply to what you need:
sLogFolder = "c:\inetpub\logs\LogFiles"
iMaxAge = 30 ' # of days
Set objFSO = CreateObject("Scripting.FileSystemObject")
set colFolder = objFSO.GetFolder(sLogFolder)
For Each colSubfolder in colFolder.SubFolders
 Set objFolder = objFSO.GetFolder(colSubfolder.Path)
 Set colFiles = objFolder.Files
 For Each objFile in colFiles
 iFileAge = now-objFile.DateCreated
 if iFileAge > (iMaxAge+1) then
 objFSO.deletefile objFile, True
 end if
 Next
Next

Save and run. *Poof* the old logs are gone. Set it up in a task scheduler and move on to more important things.

TIP: You can run the scheduled task as SYSTEM since it has privileges to run whether logged on or not. It also has access to the file system.

Hope this helps.

.Net, IIS, Programming, Web, XML

Using Encryption and Decryption on a .Net Web.Config ConnectionString

If you have .Net web applications that are connecting to data sources that you do not want other users to know about then chances are it is about time to start encrypting the connection strings. Why is this important? If you have an external website that fails (and you do not have any custom error pages) then you may expose connection information in the stack trace or error messages. Also, you do not want to allow other developers that stumble upon your connection string to see your connection information in clear text. Over time and many applications later I went from trying to remember paths and commands and have created batch files to perform this on a minimal web.config.

I am going to walk through how to create some encrypt/decrypt batch files and how these are used in conjunction with your web.config.

  • Ensure you have a .Net Framework installed to use the aspnet_regiis.exe program. For this example we are using .Net Framework 4.0.
  • Create a folder for all of your files to sit inside of. For this demo let’s call the folder “decrypter”. Make note of where you are storing this folder to use in your batch files in the next steps. For this example let’s assume “C:\decrypter”
  • Open notepad and create a file named Decrypt.bat and add the following information (take note of the path you’ll need to update based on where you are going to store your folder):
echo Decrypting connection strings
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pdf "connectionStrings" "C:\decrypter"
Pause
  • Open notepad again and create a file named Encrypt.bat and add the following information (take note of the path you’ll need to update based on where you are going to store your folder):
echo Encrypting connection strings
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pef "connectionStrings" "C:\decrypter"
Pause
  • Open notepad again and create a web.config file and insert your connectionstrings section inside (make sure to place this file in the same location as the batch files, you’ll use this over and over):
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
 <add name="Demo" connectionString="Data Source=123.45.67.89;Initial Catalog=DemoCatalog;Persist Security Info=True;User ID=specialuser;Password=specialpassword" providerName="System.Data.SqlClient" />
 </connectionStrings>
</configuration>
  • Once you have that saved, run your Encrypt.bat as administrator. You should see the following:

en-example

  • Your connection strings are now encrypted. Review your web.config and see:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">
 <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
 xmlns="http://www.w3.org/2001/04/xmlenc#">
 <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
 <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
 <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
 <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
 <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
 <KeyName>Rsa Key</KeyName>
 </KeyInfo>
 <CipherData>
 <CipherValue>You'll Have A Cipher Here.</CipherValue>
 </CipherData>
 </EncryptedKey>
 </KeyInfo>
 <CipherData>
 <CipherValue>You'll Have A Cipher Here.</CipherValue>
 </CipherData>
 </EncryptedData>
</connectionStrings>
</configuration>
  • You can now take the connectionStrings section and replace your cleartext version for your application.
  • Should you ever need to update your connectionStrings simply place the encrypted version back on your minimal web.config and run the Decrypt.bat (as administrator). This is what you should see:

de-example

  • You should then see your original clear text connection string. Hope this helps.
  • Things of note:
    • You can also do this with other sections of the web.config (just rename connectionStrings to whatever section you need to encrypt)
    • If you have comments inside of your connectionString the encryption and decryption will remove them.
    • Another reference: https://msdn.microsoft.com/en-us/library/zhhddkxy.aspx
C#, HTML, JavaScript, JSON, Programming, Web

Use No Captcha reCaptcha In ASP.Net Web Application Form Page With C#, JSON and JavaScript

Users are getting more and more tired of interpreting images with random numbers or letters that take 2-3 tries to get. Google has a new release of the reCaptcha to include a  “No Captcha” feature. You can read about that more here. Here are the steps that I took to include this newer version into a ASP.Net web application.

  • Obtain a google account and sign up for reCaptcha 
  • Create a Visual Studio C# based web forms application and create a page where you will have your reCaptcha to live
  • Download Json via NuGet (instructions are here)
  • Once you have reCaptcha information be sure to insert the following in the head section of your web page:
 
<script src="https://www.google.com/recaptcha/api.js" type="text/javascript"></script> 
  • Then place in your web page where you want the reCaptcha to live. Remember to replace “yoursitekey” with the Google reCaptcha site key:
<div class="g-recaptcha" data-sitekey="yoursitekey"></div>

 

  • Create a class in your web application called ReCaptchaClass (credit for class and credit for proxy) and put the following code into the class. Remember to replace “yoursecretkeygoeshere” with the Google reCaptcha secret key:
using Newtonsoft.Json;
    public class ReCaptchaClass
    {
        public static string Validate(string EncodedResponse)
        {
            var client = new System.Net.WebClient();
            IWebProxy defaultWebProxy = WebRequest.DefaultWebProxy;
            defaultWebProxy.Credentials = CredentialCache.DefaultCredentials;
            client.Proxy = defaultWebProxy;
            string PrivateKey = "yoursecretkeygoeshere";
            var GoogleReply = client.DownloadString(string.Format("https://www.google.com/recaptcha/api/siteverify?secret={0}&amp;response={1}", PrivateKey, EncodedResponse));
            var captchaResponse = Newtonsoft.Json.JsonConvert.DeserializeObject(GoogleReply);
            return captchaResponse.Success;
        }
        [JsonProperty("success")]
        public string Success
        {
            get { return m_Success; }
            set { m_Success = value; }
        }

        private string m_Success;
        [JsonProperty("error-codes")]
        public List ErrorCodes
        {
            get { return m_ErrorCodes; }
            set { m_ErrorCodes = value; }
        }
        private List m_ErrorCodes;
    }
  • Once the class is created place the following snippet in the code behind of your page (likely in a button click event of some kind):
string EncodedResponse = Request.Form["g-Recaptcha-Response"];
bool IsCaptchaValid = (ReCaptchaClass.Validate(EncodedResponse) == "True" ? true : false);

if (IsCaptchaValid) {
    //Valid Request
}

That’s it! Easy enough, right? I hope it helps. Questions are always welcome.

C#, HTML, JavaScript, Programming, Web

Write a JavaScript/HTML Form Submit Post From C# APSX Code Behind

There may be a case where you are taking information from a form and need to post it to a web site somewhere else. One quick method of performing that post is to execute it from the code behind using C# (via context.response) and JavaScript. This is a scaled down example of a case where I was submitting a POST from the code behind of a web part control:

A couple things to note:

  • You can add as many fields as you wish to post, I am only using two
  • You can use string.Format to get C# variables to put directly in the POST
protected string value1;
protected string value2;

value1 = "something";
value2 = "something else";

Context.Response.Write("&lt;form name='Form1' id='Form1' method='post' action='https://www.mywebsitetopostto.com/example'&gt;");
Context.Response.Write("&lt;input type='hidden' name='__VIEWSTATE' id='__VIEWSTATE' value='' /&gt;");
Context.Response.Write(string.Format("&lt;input type='hidden' name='txtValue1' id='txtValue1' runat='server' value='{0}' /&gt;", value1));
Context.Response.Write(string.Format("&lt;input type='hidden' name='txtValue2' id='txtValue2' runat='server' value='{0}' /&gt;", value2));
Context.Response.Write("&lt;/form&gt;");
Context.Response.Write("document.Form1.submit();");
Context.Response.Flush();
Context.Response.End();

Ideally you would use this in a case where you are posting content and the page you are posting to will process and serve something after the form that receives your post processes what you sent. Please do not use this snippet and blame me for a blank page 🙂

C#, Programming, SharePoint, Web

Convert A Links List To A DropDownList By A Web Part In SharePoint 2013 (C#)

So I have been enjoying the benefit of Mike Smith’s article for a while now (http://techtrainingnotes.blogspot.com/2010/12/sharepoint-convert-links-list-to.html). A client I did a project for was wanting to carry this functionality forward to 2013. The problem: this method didn’t work in 2013.

So I took a programmatic approach to lose the JavaScript dependency. It also will sort the dropdown names by what you type as the description by using the sortedlist in the code behind. It’s fairly simple, here’s what I did:

  • Created a links list and populated some URLs and Descriptions (!!! You need both for below to work, otherwise remove the description dependency in my code !!!)
  • Create a SharePoint 2013 Visual Web Part project
  • Add the dropdownlist control to the control

In the .ascx control I have:

<asp:DropDownList ID="linkDropDown" runat="server" Font-Names="Arial" Font-Size="10pt"
Width="300px" OnSelectedIndexChanged="linkDropDown_SelectedIndexChanged" AutoPostBack="true" EnableViewState="true">
<asp:ListItem Text="Link to ..." Value="#"></asp:ListItem>
</asp:DropDownList>
  • Add the code to the code behind of the control

Now the code behind, here’s my using statements:

using System;
using System.ComponentModel;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using System.Collections;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;

and here is what I have in the Page_Load and the SelectedIndexChanged event

protected void linkDropDown_SelectedIndexChanged(object sender, EventArgs e)
{
Context.Response.Redirect(linkDropDown.SelectedValue.ToString());
}

protected void Page_Load(object sender, EventArgs e)
{
SortedList sortedLists = new SortedList();

using (SPSite siteCol = new SPSite("http://mysharepoint2013site/"))
{
using (SPWeb web = siteCol.RootWeb)
{
SPList list = web.GetList("/Lists/NameOfLinksList");
SPListItemCollection items = list.GetItems();

foreach (SPListItem it in items)
{
SPFieldUrlValue fieldValue = new SPFieldUrlValue(it["URL"].ToString());
string description = fieldValue.Description;
string url = fieldValue.Url;
sortedLists.Add(description, url);
}
}

IDictionaryEnumerator enumerator = sortedLists.GetEnumerator();
while (enumerator.MoveNext())
{
ListItem listitem = new ListItem();
listitem.Text = enumerator.Key.ToString();
listitem.Value = enumerator.Value.ToString();
linkDropDown.Items.Add(new ListItem(listitem.Text.ToString(), listitem.Value.ToString()));
}
}

Deploy and enjoy!