Custom dependency resolver in regular ASP.NET Framework project

Challenge:

Implement dependency injection using IoC container – Inversion of control container (a.k.a DI container – Dependency Injection container) in ASP.NET MVC Framework project.

We will see how an IoC container like Microsoft.Extensions.DependencyInjection can be configured in the ASP.NET Framework project of MVC type.

Solution:

I have used Visual studio 2019, create a new project and add MVC and web API folder and code references. See below snapshots.

In this example, we have a property in a controller. We will try to inject IRepo instance to constructor of a controller. Consider below code for IRepo and DBRepo.

public interface IRepo
{
	string Content { get; set; }
}

public class DBRepo : IRepo
{
	private string _content;
	public string Content { get => this._content; set => this._content = value; }
}

Consider HomeController code as below.

public class HomeController : Controller
{
	public IRepo repo;

	public HomeController(IRepo vrepo)
	{
		this.repo = vrepo;
	}

	public ActionResult Index()
	{
		return View();
	}
}

This is only for demo purpose. You could provide your own inteface and its concrete class.

Install the nuget package – Microsoft.Extensions.DependencyInjection.

Add Global.asax file in the project if it does not exists.

Key place is the app_start in global.asax where our implementation is done. Most important code is as follows:

void Application_Start(object sender, EventArgs e)
{
	// Code that runs on application startup
	AreaRegistration.RegisterAllAreas();
	GlobalConfiguration.Configure(WebApiConfig.Register);
	RouteConfig.RegisterRoutes(RouteTable.Routes);

	var services = new ServiceCollection();
	services.AddTransient(typeof(IRepo), typeof(DBRepo));
	services.Add(typeof(HomeController), Lifetime.Transient);
	var defaultResolver = new DefaultDependencyResolver(services.BuildServiceProvider());

	/*
		Below code line is the key. Here we need to pass our instance implementing the desired IoC container. Since it accepts an instance of IDependencyResolver, we need to implement this interface. DefaultDependencyResolver code follows and implements the interface IDependencyResolver.

Basically, provides a registration point for dependency resolvers, using the specified dependency
        //     resolver interface.
	*/
	DependencyResolver.SetResolver(defaultResolver);  
}

And the implementation of DefaultDependencyResolver is as below.

public class DefaultDependencyResolver : IDependencyResolver
{
	private IServiceProvider serviceProvider;
	public DefaultDependencyResolver(IServiceProvider serviceProvider)
	{
		this.serviceProvider = serviceProvider;
	}

	public object GetService(Type serviceType)
	{
		return this.serviceProvider.GetService(serviceType);
	}

	public IEnumerable<object> GetServices(Type serviceType)
	{
		return this.serviceProvider.GetServices(serviceType);
	}
}

Above is the bare minimum code requied for implementing the dependency injection.

We could improvise as below and write some generic code for including all the controllers.

public class Global : HttpApplication
{
	void Application_Start(object sender, EventArgs e)
	{
		// Code that runs on application startup
		AreaRegistration.RegisterAllAreas();
		GlobalConfiguration.Configure(WebApiConfig.Register);
		RouteConfig.RegisterRoutes(RouteTable.Routes);

		var services = new ServiceCollection();
		ConfigureServices(services);
		var defaultResolver = new DefaultDependencyResolver(services.BuildServiceProvider());
		DependencyResolver.SetResolver(defaultResolver);
	}

	private void ConfigureServices(ServiceCollection services)
	{
		services.AddTransient(typeof(IRepo), typeof(DBRepo));

		services.AddMvcControllers("*");

		/*		services.AddControllersAsServices(typeof(Global).Assembly.GetExportedTypes()
		.Where(t => !t.IsAbstract && !t.IsGenericTypeDefinition)
		.Where(t => typeof(IController).IsAssignableFrom(t)
		|| t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase)));
		*/
	}
}

Below is the implementation for the extension methods on IServiceCollection.

    public static class ServiceProviderExtensions
    {
        private const string DefaultControllerFilter = "*Controller";
        /*
        public static IServiceCollection AddControllersAsServices(this IServiceCollection services, IEnumerable<Type> serviceTypes)
        {
            foreach (var type in serviceTypes)
            {
                services.AddTransient(type);
            }

            return services;
        }
        */
        public static void AddMvcControllers(this IServiceCollection serviceCollection, params string[] assemblyFilters)
        {
            serviceCollection.AddMvcControllers(GetAssemblies(assemblyFilters));
        }
        private static Assembly[] GetAssemblies(IEnumerable<string> assemblyFilters)
        {
            var assemblies = new List<Assembly>();
            foreach (var assemblyFilter in assemblyFilters)
            {
                assemblies.AddRange(AppDomain.CurrentDomain.GetAssemblies().Where(assembly => IsWildcardMatch(assembly.GetName().Name, assemblyFilter)).ToArray());
            }
            return assemblies.ToArray();
        }

        private static bool IsWildcardMatch(string input, string wildcard)
        {
            return input == wildcard || Regex.IsMatch(input, "^" + Regex.Escape(wildcard).Replace("\\*", ".*").Replace("\\?", ".") + "$", RegexOptions.IgnoreCase);
        }
        public static void AddMvcControllers(this IServiceCollection serviceCollection, params Assembly[] assemblies)
        {
            serviceCollection.AddMvcControllers(assemblies, new[] { DefaultControllerFilter });
        }

        private static void AddMvcControllers(this IServiceCollection serviceCollection, IEnumerable<Assembly> assemblies, string[] classFilters)
        {
            var controllers = GetTypesImplementing(typeof(IController), assemblies, classFilters);

            foreach (var controller in controllers)
            {
                serviceCollection.Add(controller, Lifetime.Transient);
            }
        }

        public static void Add(this IServiceCollection serviceCollection, Type type, Lifetime lifetime)
        {
            switch (lifetime)
            {
                case Lifetime.Singleton:
                    serviceCollection.AddSingleton(type);
                    break;
                case Lifetime.Transient:
                    serviceCollection.AddTransient(type);
                    break;
                default:
                    throw new ArgumentOutOfRangeException(nameof(lifetime), lifetime, null);
            }
        }

        private static IEnumerable<Type> GetTypesImplementing(Type implementsType, IEnumerable<Assembly> assemblies, params string[] classFilter)
        {
            var types = GetTypesImplementing(implementsType, assemblies.ToArray());
            if (classFilter != null && classFilter.Any())
            {
                types = types.Where(type => classFilter.Any(filter => IsWildcardMatch(type.FullName, filter)));
            }
            return types;
        }

        private static IEnumerable<Type> GetTypesImplementing(Type implementsType, params Assembly[] assemblies)
        {
            if (assemblies == null || assemblies.Length == 0)
            {
                return new Type[0];
            }

            var targetType = implementsType;

            return assemblies
                .Where(assembly => !assembly.IsDynamic)
                .SelectMany(GetExportedTypes)
                .Where(type => !type.IsAbstract && !type.IsGenericTypeDefinition && targetType.IsAssignableFrom(type))
                .ToArray();
        }

        private static IEnumerable<Type> GetExportedTypes(Assembly assembly)
        {
            try
            {
                return assembly.GetExportedTypes();
            }
            catch (NotSupportedException)
            {
                // A type load exception would typically happen on an Anonymously Hosted DynamicMethods
                // Assembly and it would be safe to skip this exception.
                return Type.EmptyTypes;
            }
            catch (FileLoadException)
            {
                // The assembly points to a not found assembly - ignore and continue
                return Type.EmptyTypes;
            }
            catch (ReflectionTypeLoadException ex)
            {
                // Return the types that could be loaded. Types can contain null values.
                return ex.Types.Where(type => type != null);
            }
            catch (Exception ex)
            {
                // Throw a more descriptive message containing the name of the assembly.
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Unable to load types from assembly {0}. {1}", assembly.FullName, ex.Message), ex);
            }
        }
    }

    public enum Lifetime
    {
        Transient,
        Singleton
    }

Use the required namespaces.

Put a break-point in HomeController constructor. Run the application in debug mode, you will see the concrete instance DBRepo is assigned to IRepo.

That’s all. Please let me know if you found it to be helpful. If yes, then please do like it and share it with your colleagues. Also, do let me know if you have any suggestion in the comment section below. Do follow this blog if you want to receive notification for the future blog posts. Thank you so much.

WordPress blog: Switch to new block editor from classic editor

Challenge: This post was not intended but since I faced a challenge while writing an another post today which involved code snippets. The code snippets were not getting displayed properly and it was adding some span tags in between the code. Basically the code tag used for code snippets did not work in classic editor of wordpress blog.

Solution: Blogger require to switch to new block editor. See below screenshot to switch to new block editor. If you do not see this option, then please clear cookies and cache of the browser. If you are unable to do it in your favorite browser, then please do it in firefox because it worked for me in this browser.

Click ‘Learn More’
Click ‘Try the block edior’
New editor – Block editor
Add a block
Since we want to add code snippets, we can select ‘SyntaxHighlighter Code’
Add the code snippet. Also, you can set appropriate settings in right pane. Settings like ‘Code Language’, line number highlighter etc.

Below is the example output:-

public class MyClass
{
	public string SomeProperty { get; set; }

	public string SomeMethod(string param)
	{
		return param;
	}
}

That’s all. Please let me know if you found it to be helpful in comments. Also do let me know if you have any suggestions too.

Visual Studio Debug issue: .NET source code file not found

Challenge: Visual studio sometimes looks for .net framework source code while debugging. It would prompt to allow download of the source code file.

dotnetframeworksourcecode_debug

If you are also facing such an issue or you do not want this behavior, then here is the solution.

Solution: Open visual studio, go to Tools > Options > Debugging > Enable Just My Code — Check this one.

It should work. Just in case, also delete the files from obj folder and bin folder of the project. Delete files from Temporary ASP.NET Files of your .NET framework version. (C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files) Restart the IIS and visual studio.

Hope this helps.

Third-party authentication to an existing regular ASP.NET MVC project

Hi Folks, this post is regarding authentication implementation with third parties like Google, Facebook, etc. in ASP.NET MVC.

Challenge: To figure out what additional code changes visual studio does when ‘Individual User Accounts’ selected in ‘Change Authentication’ while creating a project.

Solution: This code changes obtained by comparing the difference between two projects – one created with default one ‘No Authentication’ and the other created with ‘Individual User Accounts’.

The intention of this post is to observe the code changes done for the ‘Individual User Accounts’. In case of an existing project with no authentication, one could set up the third party authentication by making code changes as per the differences observed in this post.

Indeed, one can install Identity NuGet packages but it won’t add source code for App_start, Controllers, Models, Views, and Startup.

Let’s see the difference.

ProjectDifference

Copy below to packages.config file and restore them. Or find them in NuGet manager and install them.

<package id="EntityFramework" version="6.2.0" targetFramework="net472" />
<package id="Microsoft.AspNet.Identity.Core" version="2.2.2" targetFramework="net472" />
<package id="Microsoft.AspNet.Identity.EntityFramework" version="2.2.2" targetFramework="net472" />
<package id="Microsoft.AspNet.Identity.Owin" version="2.2.2" targetFramework="net472" />
<package id="Microsoft.Owin" version="4.0.0" targetFramework="net472" />
<package id="Microsoft.Owin.Host.SystemWeb" version="4.0.0" targetFramework="net472" />
<package id="Microsoft.Owin.Security" version="4.0.0" targetFramework="net472" />
<package id="Microsoft.Owin.Security.Cookies" version="4.0.0" targetFramework="net472" />
<package id="Microsoft.Owin.Security.Facebook" version="4.0.0" targetFramework="net472" />
<package id="Microsoft.Owin.Security.Google" version="4.0.0" targetFramework="net472" />
<package id="Microsoft.Owin.Security.MicrosoftAccount" version="4.0.0" targetFramework="net472" />
<package id="Microsoft.Owin.Security.OAuth" version="4.0.0" targetFramework="net472" />
<package id="Microsoft.Owin.Security.Twitter" version="4.0.0" targetFramework="net472" />
<package id="Owin" version="1.0" targetFramework="net472" />

Update the targetFramework value as yours.

Add the new source code files to your project. Click here to download the new files. Copy them to respective folders. Remember to update the namespace with your namespace.

Now to enable third party authentication, for instance, Google. Go to Startup.Auth.cs, uncomment below code and provide client id and client secret.

//app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
//{
// ClientId = "",
// ClientSecret = ""
//});

To obtain values for above two keys please refer https://developers.google.com/adwords/api/docs/guides/authentication.

Similarly, you can do for other providers.

Build and run, click login link to open the login page. You could see ‘Google’ login link.

Hope this helps to understand the additional code and how to set up authentication in already existing project manually from scratch.

PS: If you find any other challenge or have any suggestion that could improve or correct this article, please feel free to drop a comment and I will try to improve this article.

IIS load balancing in local

The objective of this post is to set up load balancing mechanism between two sites in local using IIS.

This can be helpful for the developer to reproduce issues related to the session, how static values initialization affects user experience, or load balancing in local, etc. Briefly, how the application behaves in a load balancing environment.

This post assumes the developer has already installed IIS with asp.net enabled.

Install the following IIS extensions.

  1. URL Rewrite – https://www.iis.net/downloads/microsoft/url-rewrite
  2. Application Request Routing – https://www.iis.net/downloads/microsoft/application-request-routing

Now Let’s set up two sites and load balancing for them.

  1. Run IIS Manager as Admin.

1_iis

Here we can see the Application Request Routing module and URL Rewrite module. Also, you can find the Server Farm node. Add a Default Web Site in your IIS if not present. Provide the following bindings for Default Web Site.

2_defaultsitebindingshttp

2. We need to add two sites. Right-click Sites node. Click Add Website.

3_site1

4_site2

In my case, both the site1 and site2 folders have a Default.aspx file containing content as Site1 and Site2 respectively. So, when a request made to the default page, we will know which site is serving the request.

Run notepad as Admin. Open C:\windows\system32\drivers\etc\hosts. Make the following host entries.

127.0.0.1 site2.local.com
127.0.0.1 site1.local.com
127.0.0.1 mainsite.local.com

mainsite.local.com will be the main hostname which will be used while making requests.

3. Add one more binding to each of these sites with different port numbers as shown in below images.

5_site2addbindings

We provided site1 bindings with port number 8081, empty hostname and IP as All Unassigned.

22_site1bindings

Similarly, provide site2 binding with port number 8082.

4. We will create a Server Farm. Right-click on Server Farm node. Click Create Server Farm.

6_mainsitefarm

Provide server farm name and click Next.

7_serverfarmservers

Here, provide site1.local.com in the server address. Expand the Advance Settings below. Provide httpPort and httpsPort as 8081 and 7071 respectively. Click Add Button.

Later in this post, we will create a self-signed certificate for these two domains and use that for https. Since we cannot edit this information once a server is added, we are providing httpsPort here right now.

Similarly, add second server representing site2 as shown below.

8_serverfarmservers2

So, we have considered httpPort and httpsPort as 8082 and 7072 respectively for the second server.

After adding the second server, click Finish following message pops up.

9_rewrite-rules

Click OK here. As it mentions this will create a rule which will route requests to the newly created server farm.

If you try to open http://mainsite.local.com then it will give the following error.

HTTP Error 400.605 – Bad Request

The request cannot be routed because it has reached the Max-Forwards limit. The server may be self-referencing itself in the request routing topology.

10_badrequest

Upon google search regarding the above error, we found below the post.

http://stackoverflow.com/questions/15563688/arr-the-request-cannot-be-routed-because-ithas-reached-the-max-forwards-limit

Since we have both the servers in local, we need to set port number settings of a URL rewrite rule to serve only for requests at given port.

Go to IIS Home node. Click URL Rewrite icon in the IIS section.

11_urlrewriterule

Double click the rule. It will open the following.

12_editinboundrule

Expand Conditions Accordion.

13_serverportinrule

Click Add button. Provide {SERVER_PORT} as 80 in condition. Click OK. Click Apply in the right pane.

Open http://mainsite.local.com in a browser. Now the page should load, showing either Site 1 or Site 2. Since the sticky session is disabled, it will keep changing i.e. the server will keep changing.

5. Load balancing HTTPs sites

Go to IIS Home node. Click URL Rewrite icon in the IIS section. Double click the rule if you have. Or Add a blank rule. Provide the settings in a rule as shown below.

14_urlrewritehttps

Create a self-signed certificate.

Run PowerShell with Admin. Run the following command.

New-SelfSignedCertificate -DnsName mainsite.local.com,site1.local.com,site2.local.com –
CertStoreLocation cert:\LocalMachine\My

15_powershell

Assigning HTTPs Bindings

Provide https bindings for Default Web Site with port 443 and select the mainsite.local.com from SSL Certificate dropdown.

16_defaultsitebindings

17_assignhttps

Select mainsite.local.com from the dropdown. And click OK.

Also, do the same for Site2 with port 7072.

18_badrequesterrorcode

To resolve the above issue, this link from google was helpful.

http://kundankarma.blogspot.in/2015/07/problem-statement-whenever-you-are.html

Run Certlm. In personal certificate, we see mainsite.local.com.

19_certificatecertlmpersonal

Right-click mainsite.local.com and click copy. Right-click Certificates under Trusted Root
Certification Authorities and click paste.

Now try reloading the page. It should load now and show either Site 1 or Site 2. Since the sticky session is disabled, it will keep changing i.e. the server will keep changing.

Enable Sticky Session

If you are not using session state server then you may enable sticky session. To do so, go to server farm node. Double click Server Affinity Icon.

20_serveraffinity

Check Client affinity and click apply in the right pane.

21_checkclientaffinity

Now it should retain the session.

Food for thought 🙂

Delete the existing certificates. Try creating a new self-signed certificate as given below. Run PowerShell with Admin. Run the following command.

New-SelfSignedCertificate -DnsName mainsite.local.com -CertStoreLocation
cert:\LocalMachine\My

Since the certificate is deleted, copy the certificate from Personal Certificates to Trusted Root
Certification Authorities from Certlm. Reassign the certificate in IIS Sites bindings. And test it whether it works or not. Enjoy!

Thanks to my colleague – Praveen Rekhapalli who figured out this trick.

Hope this helps.

Happy Load Balancing 🙂

Setup Sonar in local step by step

Sonar Setup
SonarQube is the central place to manage code quality, offering visual reporting on and across projects and enabling to replay the past to follow metrics evolution.
In this post, we will see how to set up Sonar in local machine step by step (for .NET). So, let’s start.

  1. Create a folder somewhere. In my case, it is C:\sonar.
  2. Download SonarQuebe from here.
    sonardownload
    Sonar Download

    Extract the zip file and copy sonarquebe folder from it to C:\sonar.
  3. Rename it to sonarqube for simplicity.
  4. So, in my case, it is C:\sonar\sonarqube. This has sonarquebe folders like bin and others.
  5. Download Sonar CSharp plugin from here.
    sonarcsharp
    Sonar CSharp Plugin
  6. Copy the plugin jar file in C:\sonar\sonarqube\extensions\plugins.
  7. Download JRE from here. In my case, I have windows 64 bit. So, I downloaded Windows x64 Offline version.
  8. Install it. Note down the path of Directory where you have installed the Java JRE. In my case, it is C:\Program Files\Java\jre1.8.0_111.
  9. Set system environment variable JAVA_HOME with above path as value. Click here to see how to set an environment variable.
  10. Update system PATH variable with ;%JAVA_HOME%\bin. Click here to see how to update the PATH variable.
  11. Download Sonar Runner from here.
  12. Unzip the file and rename the inside folder to sonar-runner for simplicity. Copy the sonar-runner folder to C:\Sonar folder. So, in my case, it will be C:\sonar\sonar-runner which has a bin folder.
  13. Set system environment variable SONAR_RUNNER_HOME to C:\sonar\sonar-runner.
  14. Update system PATH variable with ;%SONAR_RUNNER_HOME%\bin. NOTE: Values are separated by a semi-colon (;).
  15. Go to C:\sonar\sonar-runner\conf. Open sonar-runner.properties in notepad. Uncomment below the line by removing hash.
    	sonar.sourceEncoding=UTF-8
  16. Go to C:\sonar\sonarqube\conf. Open wrapper.conf in notepad. Update wrapper.java.command as below.
    	wrapper.java.command=%JAVA_HOME%\bin\java
  17. Now We will create sonar project properties files for each project. This file will have information regarding the project source code location. So, let’s create a folder somewhere. E.g. C:\TestSonar. Go inside the new folder. Right-click and create an empty file named sonar-project.properties and provide following content.
    	sonar.projectKey=TestProject1
    	sonar.projectVersion=1.0
    	sonar.projectName=TestProject1
    
    	sonar.sources=E:/sandeep/websites/TestProject1
    	sonar.language=cs
    
    	sonar.projectBaseDir=E:/sandeep/websites/TestProject1
    	sonar.dotnet.visualstudio.solution.file=TestProject1.sln
    	sonar.dotnet.4.0.sdk.directory=C:/WIndows/Microsoft.NET/Framework/v4.0.30319
    	sonar.dotnet.version=4.0
    	sonar.working.directory=C:/TestSonar/sonarworkingdir

    We have provided sonarworkingdir directory as working directory. So, create sonarworkingdir folder in TestSonar folder. Basically, if you don’t provide this property then .sonar folder will be created within the project folder given in sonar.projectBaseDir.

    Note: Do provide forward slash in path.

  18. Go to C:\sonar\sonarqube\bin\windows-x86-64 and run StartSonar.bat with admin. Wait for some time till it is up and running.
    startsonar
    StartSonar.Bat
  19. Go to C:\TestSonar where you have created the sonar-project.properties file. Run cmd as an admin here and execute the sonar-runner command.
  20. You can view the Sonar dashboard by localhost:9000 in the browser.

FAQ:

  1. How to setup Sonar for multiple projects?
    sonarmultipleprojects
    Sonar Multiple Projects

    I would suggest creating new folders named after each project. Create sonar project properties files for each project in their respective folders which will have project specific information. This helpful when you have multiple projects source codes lying in different drives or folders. Then write a batch script that will start from TestSonar folder and go inside of TestProject folders and execute sonar-runner one by one.

    In case you have a parent folder where multiple projects folders are residing then you can refer this link.
  2. How to move “.sonar” folder created in Project folder?
    Use sonar.working.directory in sonar project properties file as shown in above example. Beware: the specified folder is deleted before each analysis. I did not see any side effects of this deletion so far.
  3. What is the difference between sonarquebe and sonar-runner?
    SonarQube (formerly just “Sonar”) is a server-based system. Of course, you can install it on your local machine (the hardware requirements are minimal). But it is a central server with a database. Analyses are performed by some Sonar “client” software, which could be the sonar-runner, the sonar ant task, the sonar Eclipse plugin etc. The analysis results can be automatically uploaded to the server, where they can be accessed via the sonar Web application.(Reference)
  4. How to resolve the Wrapper stopped error?
    Run task manager as admin, and end all java.exe tasks.
    Or run cmd as admin and execute below command.
    taskkill.exe /F /IM java.exe
  5. How to resolve: ERROR: Caused by: Start pointer [line=1, lineOffset=0] should be before end pointer [line=1, lineOffset=0].
    sonarfailure_startpointer
    Sonar Runner Failure

    It has a problem with C# plugin version. (Reference)
    Go to C:\sonar\sonarqube\extensions\plugins.
    Delete sonar-csharp-plugin-5.5.0.479.jar if it is there.
    Click here to download sonar-csharp-plugin-5.3.2-RC1.jar. (Reference)
    Copy sonar-csharp-plugin-5.3.2-RC1.jar to the plugins folder.
  6. Others properties in Sonar project property file
    Click here to read more about sonar properties file.

Hope this helps. Please do provide your valuable feedback in comments below. It will help me improve the blog content.

Special Thanks to my colleagues – Praveen Rekhapalli and Akshatha Shetty.

File content not deleted completely

Challenge: We had a program that requests new xml content and write it in files. One day we started getting xml parsing error while parsing xml content from a file.

Solution: Upon investigation we found that new content is written, but old content last few lines does not get deleted as new content lines were less than old content lines. If you have new content lines greater than old content lines then there wont be any issue.

First of all, lets regenerate issue. Following code does that.

        static void Main(string[] args)
        {
            Console.WriteLine("Enter file path: ");
            string filePath = Console.ReadLine();

            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.AppendLine("Hello");
            stringBuilder.AppendLine("World");

            //Writing content first time
            WriteContent(filePath, stringBuilder.ToString());
            //File.WriteAllText(filePath, stringBuilder.ToString());

            Console.WriteLine(File.ReadAllText("temp.txt"));

            stringBuilder = new StringBuilder();
            stringBuilder.AppendLine("Hi");

            //Writing content second time. Note here content is shorter than first time
            WriteContent(filePath, stringBuilder.ToString());
            //File.WriteAllText(filePath, stringBuilder.ToString());

            Console.WriteLine(File.ReadAllText(filePath));
        }

        private static void WriteContent(string file, string content)
        {
            FileStream fileStream = null;
            StreamWriter writer = null;
            try
            {
                //FileMode.Create and FileMode.OpenOrCreate 
                fileStream = File.Open(file, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
                writer = new StreamWriter(fileStream);
                writer.Write(content);
                writer.Flush();
            }
            catch (Exception)
            {
                //log error
            }
            finally
            {
                if (writer != null)
                    writer.Close();
                if (fileStream != null)
                    fileStream.Close();
            }
        }

Run above code and you can see oworld word is left. Not completely removed.

output1
Output 1 – FileMode.OpenOrCreate

OpenOrCreate

Specifies that the operating system should open a file if it exists; otherwise, a new file should be created. If the file is opened with FileAccess.Read, FileIOPermissionAccess.Read permission is required. If the file access is FileAccess.Write, FileIOPermissionAccess.Write permission is required. If the file is opened with FileAccess.ReadWrite, both FileIOPermissionAccess.Read and FileIOPermissionAccess.Write permissions are required.

Now remove FileMode.OpenOrCreate and provide FileMode.Create.
Run and it overwrites completely.

output2
Output 2 – FileMode.Create

Create

Specifies that the operating system should create a new file. If the file already exists, it will be overwritten. This requires FileIOPermissionAccess.Write permission. FileMode.Create is equivalent to requesting that if the file does not exist, use CreateNew; otherwise, use Truncate. If the file already exists but is a hidden file, an UnauthorizedAccessException exception is thrown

Summary:

  1. So always use FileMode.Create in File.Open() to overwrite content completely.
  2. You can also use File.WriteAllText() method.

References:

https://msdn.microsoft.com/en-in/library/system.io.filemode%28v=vs.110%29.aspx

 

Mongodb database Backup and Restore

1.Open cmd with run as admin.
2.Run following command to take backup of database named analytics in mongodb.

mongodump –host XXX.XXX.XXX.XXX –port 27021 –db analytics –out E:\MongoDB\dumps

#mongodump –host <source host ip or hostname> –port <port at which mongodb is running> –db <database of which backup is required> –out <Directory path where backup would be taken>

Note this will create a folder named after your given database. It will create backup files consisting of bson and json files.

If face any issue like below.

‘mongodump’ is not recognized as an internal or external command, operable program or batch file.

Then please do provide following path or path where you have installed mongodb in Environment Variables. Provide bin folder path.

C:\Program Files\MongoDB\Server\3.0\bin

Or if you do not have time then Go to this folder from cmd as below.

cd C:\Program Files\MongoDB\Server\3.0\bin

Then run mongodump command.

3. Run following command to restore backup of database analytics.

mongorestore –host XXX.XXX.XXX.XXX –port 27021 –db analytics_new_db E:\MongoDB\dumps\analytics

#mongorestore –host <destination host ip or hostname> –port <port at which mongodb is running> –db <new or target database name> <Directory path containing bson and json files>

To confirm whether database is restored.Run following from cmd.

mongo <target hostname or hostip>:<port>
show dbs

You will see your new database. Now run following commands to see collections.

use analytics_new_db
show collections

You will see your collections of your database. Hope you enjoyed this.

Happy Database Backup and Restoring 🙂

Setup Mongodb as windows service step by step

Setup Mongodb as windows service step by step

  1. Download Mongodb from https://www.mongodb.org/downloads
  2. Install the setup.
  3. Create a directory for example E:\MongoDBDemo. And create a file here named as mongod.cfg. Provide following content in mongod.cfg.

systemLog:
destination: file
path: E:\MongoDBDemo\logs\mongod.log
storage:
dbPath: E:\MongoDBDemo\data
net:
bindIp: 127.0.0.1,xxx.xxx.xxx.xxx
port: 27021

Provide your IP instead of xxx.xxx.xxx.xxx. So multiple IP can be given comma separated.

Update the path and dbPath as per your log file path and db data folder path respectively. Click here for more configurations options.

  1. As per above path, create a folder named logs in E:\MongoDBDemo.
  1. Create a folder named data in E:\MongoDBDemo.
  1. Install windows service: If you find your mongodb.exe here – C:\Program Files\MongoDB\Server\3.0\bin\mongod.exe or please use the directory where you have installed the mongodb.

Start windows cmd with Run as Administrator and execute below command.

sc.exe create myMongodbService binPath= "C:\Program Files\MongoDB\Server\3.0\bin\mongod.exe --service --config=\"E:\MongoDBDemo\mongod.cfg\"" DisplayName= "myMongodbService" start= "auto" | net start myMongodbService

In future if you wish to delete this service then you can run following command

sc stop myMongodbService | sc delete myMongodbService

  1. Allow mongod in firewall as below. If you try to run mongod –dbpath <db path> from cmd, then you will get below dialog prompting to allow mongod against firewall.

image001

Else simply go to run window and type firewall.cpl.

image002

Click Allow a promgram or feature through Windows Firewall in left pane.

image003

Click ‘Allow another program’ button.

image004

Click Browse button and browse to C:\Program Files\MongoDB\Server\3.0\bin. Select mongod.exe and click open.

image005

Run services.msc from admin command prompt and you can see myMongodbService running.

Add, Edit and View file without svn checkout

No need to checkout a folder/file to view a file and make changes and commit. You may try below steps.

  1. Go to Run or do super+R / windows key+R
  2. Type the desired path – svn+ssh://svnbrd/abc/xyz and click OK. Repository Browser opens.
  • View File: You may browse the file you wish to view, double click the file to view or you may drag and drop the file in destination folder.
  • Edit File:
  1. Right click the file > Edit.
  2. Make changes and save.
  3. Close the file.
  4. It will show you Commit Dialog.
  5. Provide message and click OK to commit.
  • Add File: Right click folder from left pane > Add File
  • Explore Context Menu for other commands like Add Folder, Delete etc.

Happy SVN Commit!

HTH