Update json value using Newtonsoft library C#

We recently had a scenario where we needed to update the empty json array key questions with items having certain json key-value pairs containing user information.

Sample below shows part of the json to be updated:

"screens": [
                {
                  "uid": "<guid>",
                  "body": {
                    "text": "...",
                    "questions": []
                  }
			  }
		  ]

After update:

"screens": [
                {
                  "uid": "<guid>",
                  "body": {
                    "text": "...",
                    "questions": [
                      {
                        "uid": "another guid",
                        "name": "1st name",
                        .... other items
                      },
                      {
                        "uid": "another guid",
                        "name": "2nd name",
                        .... other items
                      }
                    ]
                  }
		}
	]

Below is the sample code that first removes the empty questions array and then adds it back after filling in the User information:

foreach (JToken token in jScreenItem["body"].Children())
{
	JProperty p = token as JProperty;
	if (p != null && p.Name.Contains("questions"))
	{
		token.Remove();
		break; //breaking when empty questions array is removed.
	}
}
foreach (JToken token in jScreenItem["body"].Children())
{
	JProperty p = token as JProperty;
	if (p != null && p.Name.Contains("text"))
	{
		JProperty jquestions = new JProperty("questions", JArray.FromObject(jUsers));
		token.AddAfterSelf(jquestions);
		break; //breaking when filled questions array is added.
	}
}

jUsers above is an array of Objects containing user information.

Create Virtual directory in Visual Studio 2017 IIS Express

You may be facing a scenario where the Images folder of your Project is hosted in another directory on your machine e.g. C:\Data\Images and not under the Project directory structure. In this case, if you need to check whether the Images are loading correctly, you’ll need to create a Virtual directory in your Web application/MVC/WebAPI Project.

Follow the below steps:

1. Right-click on your Project properties and go to the Web tab and provide the URL for the required Virtual directory and click on the button Create Virtual directory. This option edits the ApplicationHost.config file.

2. Run the application and right-click on the IIS Express icon in the status-bar notification tray. Select your website and open the config file.

3. Look for the site tag and find your website and you’ll find the Virtual directory nested tag. Edit the path and physicalPath attribute to the folder on your machine as shown below:

<site name="MyApi" id="2">                 
<application path="/" applicationPool="Clr4IntegratedAppPool">
<virtualDirectory path="/" physicalPath="C:\MyApi" />                 
</application>                 
<application path="/uploads" applicationPool="Clr4IntegratedAppPool">                     
<virtualDirectory path="/" physicalPath="C:\Data\Images\uploads" />                 
</application>                 
<bindings>                     
<binding protocol="http" bindingInformation="*:62216:localhost" />                 
</bindings>             
</site>

After making these changes, refresh the app to view the images in your app via localhost.

To know how to create a Virtual Directory in IIS for a website, check this post.

Show some love for the pit in my PayPal account.

Take care of your health. Click here to know more.

Join Armoney for best Cryptocurrency trading experience. Trade from anywhere, anytime!

Enable PUT and DELETE Http verbs for WebAPI with Cors on IIS 8.5

WebAPI in .Net by default allows only the GET, POST, OPTIONS and HEAD verbs. To allow PUT and DELETE, you need to remove the WebDAV handler and module from the request pipeline by making the following changes to the Web.Config.

The WebDAV element contains the settings that configure Web Distributed Authoring and Versioning (WebDAV) for Internet Information Services (IIS) 7 or above. WebDAV is an Internet-based open standard that enables editing Web sites over HTTP and HTTPS connections. You may get a 405 error code due to WebDAV.

<system.webServer>
    <handlers>
      <remove name="WebDAV" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
    <validation validateIntegratedModeConfiguration="false" />
    <modules>
      <remove name="WebDAVModule" />
    </modules>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="http://somedomain" />
        <add name="Access-Control-Expose-Headers" value="Content-Type, Accept, expiry, uid, access-token, token-type" />
        <add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS,PUT,DELETE" />
      </customHeaders>
    </httpProtocol>
  </system.webServer>

Also, the ExtensionlessUrlHandler-Integrated-4.0 handler needs to allow all verbs with a * or a manual entry for specific verbs. The minimum runtime requirement is 4.0 to make this work.

The last bit to check for a message that says e.g. PUT /Rejected-By-UrlScan . Check the logs under C:\Windows\System32\inetsrv\urlscan\Logs on the Server. You may need to edit the config file to allow those verbs or remove the UrlScan 3.1 service in the ISAPI tab of your Service in IIS which points to urlscan.dll. This is usually mentioned last in the list.

CustomHeaders are part of enabling Cors. Please note that Access-Control-Allow-Origin should not allow “*” . It should mentions specific domain that requires to be allowed for Cors. You can expose custom headers using Access-Control-Expose-Headers and allow specific methods using Access-Control-Allow-Methods.

Show some love for the pit in my PayPal account.

Implement Repository pattern with Entity Framework and C#

In the WebAPIConfig.cs file, register the repository with the Unity Container. This code file defines the delegate where you should put your Web API configuration code. Install the Unity Nuget package in your Project.

var container = new Unity.UnityContainer();

// this will register all Repositories that implement Repository<>. 
// because of the generics, you have to use the concrete type not the interface for injection
container.RegisterType(typeof(IRepository<>), typeof(Repository<>), new HierarchicalLifetimeManager());

Define the Repository interface:

public interface IRepository
{
bool Exists(int id);
IQueryable GetAll();
TEntity Get(int id);
}

Create the Abstract class for the Repository. The LogManager is for the log4net implementation for logging.

public abstract class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
	protected Models.DBEntities db = new Models.DBEntities();

	private DbContextTransaction Transaction { get; set; }

	protected static ILog log;


	public abstract TEntity Get(int id);
	public abstract IQueryable<TEntity> GetAll();

	public Repository<TEntity> BeginTransaction()
	{
		Transaction = db.Database.BeginTransaction();
		return this;
	}

	public abstract bool Exists(int id);


	// select specific columns into a DTO using specified selector
	//

	public abstract TResult Get<TResult>(int id, Expression<Func<TEntity, TResult>> selector);

	public abstract List<TResult> GetAll<TResult>(Expression<Func<TEntity, TResult>> selector);

	public Repository()
	{
		// setup the logger from the instance so we can get the derived type
		log = LogManager.GetLogger(this.GetType()); // should log as the derived type

		db.Configuration.LazyLoadingEnabled = false;

		setDBLogging();
	}

	public void logdb(string msg)
	{
		if (ConfigurationManager.AppSettings["LogDB"] == "true")
		{
			try
			{
				log.Debug(msg.Replace("\r\n", string.Empty).Replace("\n", string.Empty).Replace("\r", string.Empty));
			}
			catch (Exception ex)
			{
				log.Error("failed logging DB activity", ex);
			}
		}
	}

	public void setDBLogging()
	{
		if (ConfigurationManager.AppSettings["LogDB"] == "true")
		{
			try
			{
				db.Database.Log = msg => logdb(msg);
			}
			catch (Exception ex)
			{
				log.Error("failed setting up DB logging", ex);
			}
		}
	}

}

Example Users Respository with a transaction:

using DBMODELS = ApiPersistence.Models;
public class UsersRepository : Repository<DBMODELS.user>
{
	public override bool Exists(int id)
	{
		throw new System.NotImplementedException();
	}

	public override DBMODELS.user Get(int id)
	{
		try
		{
			IQueryable<DBMODELS.user> query = from user in db.users
											  where user.id == id
											  select user;
			var userObj = query.FirstOrDefault();


			return userObj;
		}
		catch (Exception ex)
		{
			throw ex;
		}
	}

	public override IQueryable<DBMODELS.user> GetAll()
	{
		throw new NotImplementedException();
	}
	
	public UserDTO CreateUser(){
		//Example transaction:
		using (var transaction = db.Database.BeginTransaction())
		{
			try
			{
				///code for creating user goes here...
				db.SaveChanges();

				transaction.Commit();
			}
			catch (Exception ex)
			{
				transaction.Rollback();
				log.Error("caught exception", ex);
				throw new RepositoryException("CreateMethod()", "MyRepository CreateMethod() failed", ex);
			}
		}
	}
}

Select query for many-many relationship using linq C#

Select the data between tables with many-many relationship using linq query with Entity Framework and C# as shown in the code below:

db.roles.Where(x => x.resource_id == moduleid && x.resource_type == "MyModule" && x.name == "member").SelectMany(x => x.users.Select(u=>u.id)).First();

User and Role entities in the above example have many-many relationship using a join table in the database. The above example selects the User Id with member role.

Add remove data many-many relationship Entity Framework C#

Consider the example of a Users of an application having many roles like member, admin etc. The relationship in this case is many-many. The two entities in this case are Users and Roles. The many-many relationship is handled by a join table in the database say users_roles. If you import this join table in Entity Framework, it is automatically converted into a many-many association where the Users entity holds ICollection property of Roles entity and vice-versa.

public class User{
    public int id {get; set;}
    public string firstname {get; set;}
    public string lastname {get; set;}
    public ICollection<Role> roles {get; set;}
}

public class Role{
    public int id {get; set;}
    public string name {get; set;}
    public string resource_type { get; set; }
    public Nullable<int> resource_id { get; set; }
    public System.DateTime created_at { get; set; }
    public System.DateTime updated_at { get; set; }
    public ICollection<User> users {get; set;}
}

In the below example, the DBContext object as created as db. Create the Users model object and add roles for the User. This will automatically make an entry in the join table.

//Find existing user
var user = db.users.Find(userid);

//Remove existing role
DBMODELS.role role = db.roles.Include("users").Where(x => x.resource_id == moduleid && x.resource_type == "MyModule" && x.name == "admin").FirstOrDefault();
db.roles.Remove(role);
db.SaveChanges();

//Add new role.
DBMODELS.role newrole = new DBMODELS.role();
newrole.name = "super_admin";
newrole.resource_id = moduleid;
newrole.resource_type = "MyModule";
newrole.created_at = DateTime.UtcNow;
newrole.updated_at = DateTime.UtcNow;
db.roles.Add(newrole);
db.SaveChanges();

user.roles.Add(newrole);
db.SaveChanges();

Eager loading is achieved using the Include() method above.

Resize image preserving aspect ratio in C#

The aspect ratio of an image describes the proportional relationship between its width and its height. For an x:y aspect ratio, if the width is divided into x units of equal length and the height is measured using this same length unit, the height will be measured to be y units.

The below method saves images with different encoder formats of jpeg, png and gif images. You can modify the code for other available formats in C#.

public class ImageUploader
    {

public float Save(Bitmap image, int maxWidth, int maxHeight, int quality, string fileName, string ext)
        {
            // Get the image's original width and height
            int originalWidth = image.Width;
            int originalHeight = image.Height;

            // To preserve the aspect ratio
            float ratioX = (float)maxWidth / (float)originalWidth;
            float ratioY = (float)maxHeight / (float)originalHeight;
            float ratio = Math.Min(ratioX, ratioY);

            float sourceRatio = (float)originalWidth / originalHeight;

            // New width and height based on aspect ratio
            int newWidth = (int)(originalWidth * ratio);
            int newHeight = (int)(originalHeight * ratio);

            // Convert other formats (including CMYK) to RGB.
            Bitmap newImage = new Bitmap(newWidth, newHeight, PixelFormat.Format24bppRgb);

            // Draws the image in the specified size with quality mode set to HighQuality
            using (Graphics graphics = Graphics.FromImage(newImage))
            {
                graphics.CompositingQuality = CompositingQuality.HighQuality;
                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphics.SmoothingMode = SmoothingMode.HighQuality;
                graphics.DrawImage(image, 0, 0, newWidth, newHeight);
            }

            ImageCodecInfo imageCodecInfo = null;
            // Get an ImageCodecInfo object that represents the JPEG codec.
            if (ext == ".jpg" || ext == ".jpeg")
            {
                imageCodecInfo = this.GetEncoderInfo(ImageFormat.Jpeg);
            }
            else if (ext == ".png")
            {
                imageCodecInfo = this.GetEncoderInfo(ImageFormat.Png);
            }
            else if (ext == ".gif")
            {
                imageCodecInfo = this.GetEncoderInfo(ImageFormat.Gif);
            }

            // Create an Encoder object for the Quality parameter.
            Encoder encoder = Encoder.Quality;

            // Create an EncoderParameters object. 
            EncoderParameters encoderParameters = new EncoderParameters(1);

            // Save the image as a JPEG file with quality level.
            EncoderParameter encoderParameter = new EncoderParameter(encoder, quality);
            encoderParameters.Param[0] = encoderParameter;
            newImage.Save(uploadsdir + fileName, imageCodecInfo, encoderParameters);

            return sourceRatio;
        }
}
private ImageCodecInfo GetEncoderInfo(ImageFormat format)
        {
            return ImageCodecInfo.GetImageDecoders().SingleOrDefault(c => c.FormatID == format.Guid);
        }

Call the code above with the following parameters as below, keeping the following points in mind:

  • SaveImages method below is created keeping in mind, it is written for a WebAPI and the image may be received in the byte array format.
  • Use a very large height value, so the new image is re-sized restricted to new width size for thumb, medium and large sizes based on the aspect ratio.
  • The Quality category specifies the level of compression for an image. When used to construct an EncoderParameter, the range of useful values for the quality category is from 0 to 100. The lower the number specified, the higher the compression and therefore the lower the quality of the image. Zero would give you the lowest quality image and 100 the highest.
public string SaveImages(byte[] imgArr, string filename, string extension, string uploadtype, out float ratio)
        {
            const int THUMB_WIDTH = 120;
            const int MEDIUM_WIDTH = 400;
            const int LARGE_WIDTH = 900;
            const int IMG_HEIGHT = 100000;
            const int IMG_QUALITY = 100;
            ratio = 0.0f;
            string[] extensionwhitelist = new string[] { ".jpg", ".jpeg", ".gif", ".png" };

            ImageUploader uploader = new ImageUploader(uploadtype);
            
            var encfilename = encryptfilename(filename);
            try
            {
                if (!extensionwhitelist.Contains(extension))
                {
                    throw new Exception("Invalid File format.");
                }
                
                TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap));
                Bitmap bitmapImg = (Bitmap)tc.ConvertFrom(imgArr);

                uploader.SaveOriginal(bitmapImg, IMG_QUALITY, encfilename + extension, extension);
                uploader.Save(bitmapImg, THUMB_WIDTH, IMG_HEIGHT, IMG_QUALITY, "thumb_" + encfilename + extension, extension);
                uploader.Save(bitmapImg, MEDIUM_WIDTH, IMG_HEIGHT, IMG_QUALITY, "medium_" + encfilename + extension, extension);
                ratio = uploader.Save(bitmapImg, LARGE_WIDTH, IMG_HEIGHT, IMG_QUALITY, "large_" + encfilename + extension, extension);
            }
            catch(Exception ex)
            {
                throw new BusinessServiceException("SaveImages", "Failed saving images.", ex);
            }

            return encfilename;
        }

The method encryptfilename can be written using a method of choice for encrypting the filename of the image.

TLS version handling with http web request CSharp

Since you’re reading this, probably your C# code broke the connection to the website or a third-party API you’re hitting using the HttpWebRequest. The below code shows one such scenario where my application code broke which is running in .net framework 4.0. The company running the API upgraded their security with the TLS version upgrade to 1.2.

The exception that you’re seeing as below while trying to call GetResponse():

The request was aborted: Could not create SSL/TLS secure channel.

Uri url = new Uri(Link);
HttpWebRequest http = (HttpWebRequest)WebRequest.Create(url.ToString());
HttpWebResponse resp = (HttpWebResponse)http.GetResponse();
returnValue = Convert.ToInt32(resp.StatusCode);

HTTPS relies on a family of lower level security protocol implementations called transport level security (TLS), each using different cryptographic algorithms. Transport Layer Security (TLS) is a cryptographic protocol used to establish a secure communications channel between two systems. Anything that is using TLS standard below TLS 1.2 is considered to be non secure because these older encryption algorithms have been cracked at some point. The TLS standards keep evolving and TLS 1.3 is in the works.

Each .net framework supports TLS version 1.2 in the following ways:

  • .Net 4.5 and above: Add the below line of code before making the web request in your code. Some blogs say .Net 4.6 and above support it by default and no code changes are required but as I tried it myself, it doesn’t work.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
  • .Net 4.0: This framework does not support the enumeration as in the latest frameworks, the below line of code helps achieve that:
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

Older frameworks do no support the latest TLS version, so it’s better to upgrade your application. Also, as a good security practice do not use the fallback code as shown below:

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

Another good point to consider upgrading your application is to check if Microsoft still supports the .Net framework you’re using.

Show some love for the pit in my PayPal account.

ASP.Net Server side Http Web Request with Custom Headers

This post shows how to make HttpWebRequest from Asp.Net page using c#. Here, the requirement is to call an external API with Custom headers and sending json data in the page_load method. Reading the Html response from the stream and write it on the Aspx page. Gluid is the Global Unique Identifier generated in c#.

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL + "?pID=" + pID);

NameValueCollection nameValueCollection = new NameValueCollection
{
{ "firstName", firstName },
{ "lastName", lastName },
{ "x-requestKey", Gluid },
};
request.Headers.Add(nameValueCollection);
request.Accept = "application/json";
request.ContentType = "application/json";
request.Method = "POST";
request.AllowAutoRedirect = true;
byte[] bytes = Encoding.ASCII.GetBytes(dataSent);

request.ContentLength = bytes.Length;
Stream os = request.GetRequestStream();
os.Write(bytes, 0, bytes.Length); //Push it out there
os.Close();

Stream responseStream = httpWebResponse.GetResponseStream();
StreamReader streamReader = new StreamReader(responseStream, Encoding.UTF8);
string html = streamReader.ReadToEnd();
Response.Write(html);

dataSent is the is json data read from a json file and sent as bytes.

For generating Gluid, use the following C# code:

public string GetUniqueIdentifier()
{
var guid = Guid.NewGuid().ToString();
return guid;
}

For similar Http POST request using jquery ajax, check out this post.

Http POST request with jQuery ajax

One of the most common scenarios is making client side Http calls to URLs to external or internal domain using jQuery ajax. In this demo, I’ll show how to call Page static method of an ASP.net method written for an aspx page using C#. The requirement is to use headers that need to be passed along with POST data.

var dataSent = "{firstName : '" + firstName + "', lastName: '" + lastName + "', pID: '" + pID + "'}";

I used the following Javascript method to generate Guid which is RFC4122 version 4 compliant solution.

var Guid = createGuid();

function createGuid() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}

Below is the jQuery ajax POST request calling the Page static method DemoMethod in the DemoPage.aspx.cs file with the following signature:

Server-side public static method:

[WebMethod]

public static string DemoMethod(string firstName, string lastName, string pID) {return "demo";}

Client-side jquery ajax call:

$.ajax({
type: ‘POST’,
url: “DemoPage.aspx/DemoMethod”,

contentType: “application/json; charset=utf-8”,
dataType: ‘json’,
headers: {
‘Accept’: ‘application/json’,
‘Content-Type’: ‘application/json’,
‘firstName’: firstName,
‘lastName’: lastName,
‘x-requestKey’: Guid
},
data: dataSent,
async: false,
success: function (response) {
alert(response);
if (response != null && response.d != null) {
alert(response.d);
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
alert(‘error’);
}
});

The response in the success part will be received by the object “response” and can be accessed using the response.d property.