How to change Application scope Settings (that are read-only) at runtime in C#

If you set your settings to the "Application" scope the settings will be read-only.

If you want to change these settings at runtime, you can use the following code from my unit test project:

 

First create a Settings class in your unit test project:

Right click on the unit test project and choose "Properties".

Click on "Settings":

Click on "This project does not contain a default settings file. Click here to create one."

 

image

 

At two test settings: "MyStringSetting" and "MyInSetting"":

 

image

 

image

 

The App.config will be changed like:

image

 

Now to show the code that changes the settings at runtime:

 

namespace UnitTestProject2
{
    using System;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using UnitTestProject2.Properties;

    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            var settings = new Settings();
            
            Assert.AreEqual(settings.MyStringSetting, "This is some random text.");
            settings.ChangeSetting("MyStringSetting", "This is some other text.");
            Assert.AreEqual(settings.MyStringSetting, "This is some other text.");

            Assert.AreEqual(settings.MyIntSetting, 999);
            settings.ChangeSetting("MyIntSetting", 100);
            Assert.AreEqual(settings.MyIntSetting, 100);
        }
    }
    
}

namespace UnitTestProject2.Properties
{
    internal sealed partial class Settings
    {
        public void ChangeSetting<T>(string key, T value)
        {
            this[key] = value;
        }
    }
}

How to set / overwrite the Context.User.IsInRole for debugging/testing purposes in C#

In my case I wanted to debug a ASP .NET MVC application, that used Windows authentication, but my account was not added to the "Administrators" role in development. If you still want to debug the site as an Administrator you can set the role of the authenticated user in the Global.asax.

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    if (Context.User != null)
    {
        var userPrincipal = new GenericPrincipal(Context.User.Identity, new string[] { "Adminstrators" });
        Context.User = userPrincipal;
    } 
}

How to dynamically call an action in Outsystems, based on the eSpace name and Action name.

This post describes how to call an action in Outsystems, based on a given eSpace name and action name.

 

Lets says you want the user to select a action name from a dropdownlist and execute this action, then you can create a big switch statement to call the actions supplied in the dropdownlist, but if you don’t want to change this switch statement each time a new action is added to the list, then you have to create an Outsystems actions and write some C# code, to dynamically execute the action based on a given eSpace name and action name.

 

Extension

image

 

Visual Studio

image

 

C# code

namespace OutSystems.NssDynamicExtension {

using System;
using System.Collections;
using System.Data;
using OutSystems.HubEdition.RuntimePlatform;
using GotDotNet.ApplicationBlocks;
using System.Text;
using System.Linq;
using System.Reflection;

public class CssDynamicExtension: IssDynamicExtension {

/// <summary>
/// 
/// </summary>
/// <param name="ssresult"></param>
/// <param name="sseSpaceName"></param>
/// <param name="ssactionName"></param>
public void MssInvokeAction(out string ssresult, string sseSpaceName, string ssactionName) {
    ssresult = string.Empty;
    var messages = new StringBuilder(string.Empty);

    try
    {

        // Get all assemblies in current AppDomain.
        AppDomain currentDomain = AppDomain.CurrentDomain;
        Assembly[] assemblies = currentDomain.GetAssemblies();

        // Log all assemblynames.
        assemblies.ToList()
            .OrderBy(x => x.FullName).ToList()
            .ForEach(x => { messages.AppendLine(x.GetName().Name); });

        // Get eSpace assembly.
        Assembly eSpaceAssemlby = assemblies.ToList()
                    .First(x => x.GetName().Name.Equals(sseSpaceName, StringComparison.InvariantCultureIgnoreCase));

        // Get assembly that contians the "HeContext" type.
        Assembly runtimePlatform = assemblies.ToList()
                .First(x => x.GetName().Name.Equals("OutSystems.HubEdition.RuntimePlatform"));

        // Get the type that contains all actions from an eSpace.
        Type actionsType = eSpaceAssemlby.GetType(string.Format("ss{0}.Actions", sseSpaceName));

        // Get "HeContext" type (curent HttpContext object).
        Type contextType = runtimePlatform.GetType("OutSystems.HubEdition.RuntimePlatform.HeContext");

        // Create an instance of the "HeContext" type.
        object contextInstance = Activator.CreateInstance(contextType);

        // Invoke the given action and supply as first parameter the "HeContext" (curent HttpContext) object.
        actionsType.InvokeMember(string.Format("Action{0}", ssactionName), 
                                BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public, 
                                null, null, new object[] { contextInstance });
    }
    catch (Exception ex)
    {
        messages.AppendLine(ex.ToString());
    }

    ssresult = messages.ToString();
} // MssInvokeAction

} // CssDynamicExtension

} // OutSystems.NssDynamicExtension

 

Use the action in Outsystems

image

 

Result

image

 

The action that was dynamically invoked, inserted a record in the database and I could see this record was created, so everything worked just fine.

 

So instead of:

image

 

My code now looks like this:

 

image

 

 

Sometimes, reflection is your friend Smile.

How to dynamically bind data to Content Controls in a Microsoft Word document by using OpenXml and C#.

 

Create a new Microsoft Word document add two content controls with the names:

  • Employee_Firstname
  • Employee_Lastname

Like:

image

 

Employee_Lastname

 

image

 

Now when you run the unittest below, the following the result will be:

 

image

 

 

namespace EndToEndTest
{
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.CustomXmlDataProperties;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
[TestClass]
public class RliResearch
{
private List<string> _tagNames = new List<string>();
private List<string> _uniqueTagNames = new List<string>();
[TestMethod]
public void Test_with_duration()
{
var watch = new System.Diagnostics.Stopwatch();
watch.Start();
InitialiseDatabinding();
watch.Stop();
System.Console.WriteLine(watch.Elapsed.TotalMilliseconds);
}
public void InitialiseDatabinding()
{
using (WordprocessingDocument doc = WordprocessingDocument.Open(@"C:\Temp\Test.docx", true))
{
CustomXmlPart customXmlPart = doc.MainDocumentPart.CustomXmlParts.FirstOrDefault();
if (customXmlPart == null)
{
customXmlPart = doc.MainDocumentPart.AddCustomXmlPart(CustomXmlPartType.CustomXml);
}
if (customXmlPart.CustomXmlPropertiesPart == null)
{
customXmlPart.AddNewPart<CustomXmlPropertiesPart>();
}
var propertiesPart = customXmlPart.CustomXmlPropertiesPart;
if(propertiesPart.DataStoreItem == null)
{
var dataStoreItem = new DataStoreItem() { ItemId = Guid.NewGuid().ToString("B") };
propertiesPart.DataStoreItem = dataStoreItem;
}
string dataStoreId = customXmlPart.CustomXmlPropertiesPart.DataStoreItem.ItemId;
var names = new List<string>();
foreach (var cc in doc.ContentControls())
{
SdtProperties props = cc.Elements<SdtProperties>().FirstOrDefault();
if (props != null)
{
string name = string.Empty;
try
{
Tag tag = props.Elements<Tag>().FirstOrDefault();
if (tag != null)
{
name = tag.Val.ToString();
names.Add(name);
tag.Val = name;
DocumentFormat.OpenXml.Wordprocessing.SdtAlias alias = props.Elements<DocumentFormat.OpenXml.Wordprocessing.SdtAlias>().FirstOrDefault();
if (alias != null)
{
alias.Val = name;
}
// Update databinding
DocumentFormat.OpenXml.Wordprocessing.DataBinding dataBinding = props.Elements<DocumentFormat.OpenXml.Wordprocessing.DataBinding>().FirstOrDefault();
if (dataBinding == null)
{
dataBinding = new DataBinding();
dataBinding.XPath = string.Format("/Root[1]/{0}[1]", name);
dataBinding.StoreItemId = dataStoreId;
props.Append(dataBinding);
}
else
{
dataBinding.XPath = string.Format("/Root[1]/{0}[1]", name);
dataBinding.StoreItemId = dataStoreId;
}
}
}
catch (Exception ex)
{
throw new ApplicationException(string.Format("Exception found during processing of tag [{0}].", name), ex);
}
}
}
List<string> uniqueTagNames = names.Distinct(StringComparer.CurrentCultureIgnoreCase).OrderBy(x => x).ToList();
XDocument xdoc = CreateXmlDocument("Root", uniqueTagNames);
SaveCustomXmlPart(customXmlPart, xdoc);
}
}
/// <summary>
/// Create a XDocument, with a root element based on the given "rootName", containing child elements based on the given "tagnames".
/// </summary>
public XDocument CreateXmlDocument(string rootName, List<string> tagNames)
{
var document = new XDocument(
new XDeclaration("1.0", "utf-8", null),
new XElement(rootName,
tagNames.Select(x => 
{
XElement xe = new XElement(x, string.Empty);
if(string.Compare(x, "Employee_Firstname", true) == 0)
{
xe = new XElement(x, "Johny");
}
if (string.Compare(x, "Employee_Lastname", true) == 0)
{
xe= new XElement(x, "Droptables");
}
return xe;
}
)
)
);
return document;
}
public void SaveCustomXmlPart(CustomXmlPart part, XDocument xdoc)
{
using (var stream = part.GetStream(FileMode.Create, FileAccess.ReadWrite))
{
// Reset stream position to 0, to prevent errors.
stream.Position = 0;
using (XmlWriter xw = XmlWriter.Create(stream))
{
xdoc.Save(xw);
}
}
}
}
/// <summary>
/// Code from: http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2011/04/11/137383.aspx
/// </summary>
public static class ContentControlExtensions
{
public static IEnumerable<OpenXmlElement> ContentControls(
this OpenXmlPart part)
{
return part.RootElement
.Descendants()
.Where(e => e is SdtBlock || e is SdtRun);
}
public static IEnumerable<OpenXmlElement> ContentControls(
this WordprocessingDocument doc)
{
foreach (var cc in doc.MainDocumentPart.ContentControls())
yield return cc;
foreach (var header in doc.MainDocumentPart.HeaderParts)
foreach (var cc in header.ContentControls())
yield return cc;
foreach (var footer in doc.MainDocumentPart.FooterParts)
foreach (var cc in footer.ContentControls())
yield return cc;
if (doc.MainDocumentPart.FootnotesPart != null)
foreach (var cc in doc.MainDocumentPart.FootnotesPart.ContentControls())
yield return cc;
if (doc.MainDocumentPart.EndnotesPart != null)
foreach (var cc in doc.MainDocumentPart.EndnotesPart.ContentControls())
yield return cc;
}
}
}

How to create a Microsoft SharePoint folder in a document library, by using WebClient in C#

 

If you want to create a folder in a document library, by using WebClient in C#, you can use the following code:

 

namespace Research
{
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Net;
[TestClass]
public class RliResearch
{
[TestMethod]
public void CreateSharePointFolderInDocumentLibrary()
{
string folderToCreateUri = "https://1.1.1.1/sites/mysite/Shared%20Documents/FolderIWantToCreate";
using (var client = new WebClient())
{
client.Credentials = CredentialCache.DefaultCredentials;
client.UploadString(folderToCreateUri, "MKCOL", "");
}
}
}
}

Note: The folder you want to create the folder in, must exist. In other words: create subfolder hierarchy one at a time.

To create the folder hierarchy:

Shared Documents

     SubLevel1

             SubLevel2

 

namespace Research
{
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Net;
[TestClass]
public class RliResearch
{
[TestMethod]
public void CreateSharePointFolderInDocumentLibrary()
{
string sublevel1 = "https://1.1.1.1/sites/mysite/Shared%20Documents/SubLevel1";
using (var client = new WebClient())
{
client.Credentials = CredentialCache.DefaultCredentials;
client.UploadString(sublevel1, "MKCOL", "");
}
string sublevel2 = "https://1.1.1.1/sites/mysite/Shared%20Documents/SubLevel1/SubLevel2";
using (var client = new WebClient())
{
client.Credentials = CredentialCache.DefaultCredentials;
client.UploadString(sublevel2, "MKCOL", "");
}
}
}
}

Combine base URL string with a relative path string in C#

One way of combining a base URL string with a relative path string in C#:

 

[TestMethod]
public void Combine_base_url_with_relative_path_test()
{
Char slash = '/';
// Make sure sharePointUrl does not end with a slash.
string sharePointUrl = "https://mySharePointServer/sites/mysites";
if (sharePointUrl.EndsWith(slash.ToString()))
{
sharePointUrl = sharePointUrl.TrimEnd(slash);
}
// Make sure templatesRelatviePath does not start with a slash.
string templatesRelatviePath = "Shared Document/SubFolder1/SubFolder2";
if (templatesRelatviePath.StartsWith(slash.ToString()))
{
templatesRelatviePath = templatesRelatviePath.TrimEnd(slash);
}
string templateAbsolutePath = string.Format("{0}{1}{2}", sharePointUrl, slash, templatesRelatviePath);
// Assert
Assert.AreEqual("https://mySharePointServer/sites/mysites/Shared Document/SubFolder1/SubFolder2", 
templateAbsolutePath);
}

image

POST multiple parameters to an ASP .NET Web Api REST service from a .NET 3.5 assembly, by using one dynamic JObject "options" parameter.

 

Client code in .NET 3.5

 

namespace WordMerge.EndToEndTests
{
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Net;
using Newtonsoft.Json;
[TestClass]
public class UnitTest1
{
[TestMethod]
public void Execute_a_post_request()
{
string url = "http://localhost:63544/api/document";
object result = string.Empty;
// Uses the System.Net.WebClient and not HttpClient, because .NET 2.0 must be supported.
using (var client = new WebClient())
{
// Set the header so it knows we are sending JSON.
client.Headers[HttpRequestHeader.ContentType] = "application/json";
// Create the one and only "options" parameter object.
var dto = new DocumentDto
{
TemplatePath = @"C:\Temp\Templates",
DestinationPath = @"C:\Temp\Destination",
Data = new string[] { "This", " is", " test", " input", " data." }
};
// Serialise the data we are sending in to JSON
string serialisedData = JsonConvert.SerializeObject(dto);
// Make the request
var response = client.UploadString(url, serialisedData);
// Deserialise the response into a GUID
result = JsonConvert.DeserializeObject(response);
}
Assert.AreEqual(@"Succesfully uploaded: This, is, test, input, data.", result.ToString());
}
}
public class DocumentDto
{
public string TemplatePath { get; set; }
public string DestinationPath { get; set; }
public string[] Data { get; set; }
}
}

Server code in .NET 4.5

 

 

namespace Service.api
{
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
public class DocumentController : ApiController
{
// GET api/<controller>
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/<controller>/5
public string Get(int id)
{
return "value";
}
// POST api/<controller>
public string Post([FromBody]JObject jsonData)
{
// Convert the dynamic JObject to a DocumentDto object.
DocumentDto dto = jsonData.ToObject<DocumentDto>();
// Use the given data to create the result.
string seperator = ",";
string data = string.Join(seperator, dto.Data.ToList<string>());
string result = string.Format("Succesfully uploaded: {0}", data);
return result;
}
// PUT api/<controller>/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/<controller>/5
public void Delete(int id)
{
}
}
public class DocumentDto
{
public string TemplatePath { get; set; }
public string DestinationPath { get; set; }
public string[] Data { get; set; }
}
}

How to POST a string[] array to a ASP .NET Web Api REST service that uses JSON, from a .NET 2.0 assembly

In this post I will use a UnitTest project written in C# .NET 2.0 as client code.

And a ASP .NET Web Api project as Server (service).

 

Client code

Create a new UnitTest project and change target framework to .net 3.5.

Add nuget package JSON.NET.

 

 

 

 

namespace WordMerge.EndToEndTests
{
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Net;
using Newtonsoft.Json;
[TestClass]
public class UnitTest1
{
[TestMethod]
public void Execute_a_get_request()
{
string url = "http://localhost:63544/api/document";
string result = string.Empty;
// Uses the System.Net.WebClient and not HttpClient, because .NET 2.0 must be supported.
using (var client = new WebClient())
{
// Set the header so it knows we are requesting JSON.
client.Headers[HttpRequestHeader.ContentType] = "application/json";
result = client.DownloadString(url);
}
Assert.AreEqual(@"[""value1"",""value2""]", result);
}
[TestMethod]
public void Execute_a_post_request()
{
string url = "http://localhost:63544/api/document";
object result = string.Empty;
// Uses the System.Net.WebClient and not HttpClient, because .NET 2.0 must be supported.
using (var client = new WebClient())
{
// Set the header so it knows we are sending JSON.
client.Headers[HttpRequestHeader.ContentType] = "application/json";
string[] data = new string[] { "This", " is", " test", " input", " data." };
// Serialise the data we are sending in to JSON
string serialisedData = JsonConvert.SerializeObject(data);
// Make the request
var response = client.UploadString(url, serialisedData);
// Deserialise the response into a GUID
result = JsonConvert.DeserializeObject(response);
}
Assert.AreEqual(@"Succesfully uploaded: This, is, test, input, data.", result.ToString());
}
}
}

NuGet packages config

 

<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="5.0.6" targetFramework="net35" />
</packages>

Server (service) code

Create an empty ASP .NET Web API project in Microsoft Visual Studio 2013.

namespace Service.api
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
public class DocumentController : ApiController
{
// GET api/<controller>
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/<controller>/5
public string Get(int id)
{
return "value";
}
// POST api/<controller>
public string Post([FromBody]string[] values)
{
string seperator = ",";
string data = string.Join(seperator,values.ToList<string>());
string result = string.Format("Succesfully uploaded: {0}", data);
return result;
}
// PUT api/<controller>/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/<controller>/5
public void Delete(int id)
{
}
}
}

Visual Studio Structure

image

NuGet packages config

<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AspNet.WebApi" version="5.0.0-rc1" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.0.0-rc1" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.0.0-rc1" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.0.0-rc1" targetFramework="net45" />
<package id="Newtonsoft.Json" version="4.5.11" targetFramework="net45" />
</packages>

Nice Visual Studio extension: Pretty Paste

 

image

 

Sometimes you just one to copy and past some code from a web site into Microsoft Visual Studio, but then you will have to reformat that code, not any more thanks to the free Microsoft Visual Studio extension Pretty Paste:

 

http://visualstudiogallery.msdn.microsoft.com/6a23234d-45f6-4212-bac3-f6d9bb08fb1e

http://madskristensen.net/post/Introducing-Pretty-Paste-for-VS2012.aspx