Ehsan Ghanbari

Experience, DotNet, Solutions

The combination of Stackify and Netling are doing a great job!

There are lots of tools and libraries out there for monitoring the Dot Net web applications. I personally use several tools based on my need. One of the tools I've always liked is Netling. It's great for fetching some overall results about the load time and resource usages of the application on heavy requests.  Rather than that, I usually use another code monitoring tool to see what's going exactly in my code. Get the latest version of Stackify and Netling. Firstly, run the Netling client and test your application load via different Threads, I'm testing the app on my website source code:

 

 

You can see the result in the picture above for 16 threads. Note that I'm running the app on my local computer machine and running on the web server would appear different result:

 

 

Anyway, you can see about the details of each parameter of Netling over here. Netling gives us overall result about the load and performance but it doesn't give us which section or which method causes the load issue. As I told, Stackify is a great tool for code monitoring; After installing and enabling the application via the mentioned link at the beginning of the post, run your application and see the result in the local address that Stackify gives you:

 

 

It's obviously shown that which action takes more time than others. And by selecting the action on the left side you can see the details on the right side. You can detect the heavy queries and modify them. needless to say that, Stackify code monitoring and you can only use it in your local machine on your source code.



Using glimps in asp.net mvc

I've always loved and used Glimpse at least for my basic performance and load test in my asp.net MVC projects. It's really straightforward and easy to use web debugging and diagnostics tool. Get the latest version of the library from nuget and get started. After installing the suitable version based on your MVC version, go to the yourApplicationUrl/Glimpse.axd and enable it.

 

 

Then you will see the Glimpse layout at the bottom of every page of your application:

 

 

After redirecting to the different page, you can easily see the details of your request such as Execution, Metadata, Model Binding, Routes, and even SQL queries:

 

 

Glimpse just inform you about your application, You can use this tool in your application I recommend you to close it in final production:

 

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");  

 

 



Image browse plugin in CKEditor

I was recently integrating my blog with CKEditor Image Browser plugin and it was interesting to me, It was cool! in order to add Image Browser plugin to your CKEditor you should get the file from the mentioned link and put it in your plugins folder inside CKEditor. Then you should go to the config.js file of CKEditor and add the target plugin:

CKEDITOR.editorConfig = function( config ) {

// Define changes to default configuration here. For example:

// config.language = 'fr';

// config.uiColor = '#AADC6E';

    config.extraPlugins = 'imagebrowser';

    config.extraPlugins = 'prism';

    config.extraPlugins = 'codesnippet';

    config.extraPlugins = 'widget';

    config.extraPlugins = 'dialog';

};

Now before browsing, if you run your application, you would see the image properties with  Browse server button:

 

 

Now you should tell the plugin that where your images should be getting, imageBrowser_listUrl is the URL which should return a JSON file:

 <textarea id="my-textarea-id"></textarea>

 <script type="text/javascript">

    CKEDITOR.replace('js-my-textarea', {

        "extraPlugins": 'imagebrowser',

        "imageBrowser_listUrl": "/Administrator/File/BrowseImages"

    });

</script>

As I've written my blog with MVC4, I used HTML helper instead of <textarea> tag:

     @Html.TextAreaFor(blog => blog.Body, new { @id = "js-my-textarea", @class = "ckeditor" })

Image browser in CKEditor needs the JSON result in a format like this:

[

        {

                "image": "/image1.jpg",

                "thumb": "/image1_thumb.jpg"

        },

        {

                "image": "/image2_.jpg",

                "thumb": "/image2_thumb.jpg"                

        },

]

To create a JSON file like this in MVC, make JsonResult with the same output:

 public JsonResult BrowseImages()

        {

            var imageBrowser = new List<ImageBrowserViewModel>();

            var path="/Images/"

            var images = Directory.GetFiles(Server.MapPath(path)).OrderByDescending(d => new FileInfo(d).CreationTime);

            foreach (var image in images)

            {

                imageBrowser.Add(new ImageBrowserViewModel

                {

                    image = string.Format(finalPath + Path.GetFileName(image)),

                    thumb = string.Format(finalPath + "Thumb/" + Path.GetFileName(image)),

                });

            }

            return Json(imageBrowser, JsonRequestBehavior.AllowGet);

        }

And the ImageBrowserViewModel is just a ViewModel to initiate the output:

 public class ImageBrowserViewModel

    {

        public string image { get; set; }

 

        public string thumb { get; set; }

    }

As you can see in my code and also based on the required JSON output, I save the thumb of my images to show them in image browser to pick. Now you can see the output of your plugin in your editor:

  



Using FluentFTP in Asp.net applications

FluentFTP is a lightweight opensource library for FTP operations and I have used it several times in the applications I have worked on. You can refer to the documentation of the project on GitHub for more information. But I'm just gonna to share you the distilled helper I'm using for FluentFTP.

 

 

 public class FtpManager

    {

        private readonly string _ftpUrl;

        private readonly string _username;

        private readonly string _password;

 

        public FtpManager(string ftpUrl, string username, string password)

        {

            if (string.IsNullOrEmpty(ftpUrl))

            {

                throw new ArgumentNullException(nameof(ftpUrl));

            }

 

            if (string.IsNullOrEmpty(username))

            {

                throw new ArgumentNullException(nameof(username));

            }

 

            if (string.IsNullOrEmpty(password))

            {

                throw new ArgumentNullException(nameof(password));

            }

 

 

            if (!ftpUrl.StartsWith("ftp://"))

            {

                ftpUrl = $"ftp://{ftpUrl}";

            }

 

            _ftpUrl = ftpUrl;

            _username = username;

            _password = password;

        }

 

        public void UploadFile(AttachmentFileModel attachmentFileModel)

        {

            try

            {

                var client = new FtpClient(_ftpUrl);

 

 

                byte[] data;

                using (var inputStream = attachmentFileModel.HttpPostedFileBase.InputStream)

                {

                    var memoryStream = inputStream as MemoryStream;

                    if (memoryStream == null)

                    {

                        memoryStream = new MemoryStream();

                        inputStream.CopyTo(memoryStream);

                    }

 

                    data = memoryStream.ToArray();

                }

 

                client.Credentials = new NetworkCredential(_username, _password);

                client.Connect();

                var path = CreateDirectory(attachmentFileModel, client);

                client.Upload(data, path + attachmentFileModel.ContentName);

                client.Disconnect();

            }

            catch (Exception exception)

            {

                //Log

            }

        }

 

        public void UpdateFile(AttachmentFileModel attachmentFileModel)

        {

            try

            {

                var client = new FtpClient(_ftpUrl);

 

                byte[] data;

                using (var inputStream = attachmentFileModel.HttpPostedFileBase.InputStream)

                {

                    var memoryStream = inputStream as MemoryStream;

                    if (memoryStream == null)

                    {

                        memoryStream = new MemoryStream();

                        inputStream.CopyTo(memoryStream);

                    }

 

                    data = memoryStream.ToArray();

                }

 

                client.Credentials = new NetworkCredential(_username, _password);

                client.Connect();

                var path = CreateDirectory(attachmentFileModel, client);

                client.Upload(data, path + attachmentFileModel.ContentName);

                client.Disconnect();

            }

            catch (Exception exception)

            {

                //Log it

            }

        }

 

        public void DeleteFile(AttachmentFileModel attachmentFileModel)

        {

            try

            {

                var client = new FtpClient(_ftpUrl);

                client.Credentials = new NetworkCredential(_username, _password);

                client.Connect();

                var path = CreateDirectory(attachmentFileModel, client);

 

                if (client.FileExists(path + attachmentFileModel.ContentName))

                {

                    client.DeleteFile(path + attachmentFileModel.ContentName);

                }

 

                client.Disconnect();

            }

            catch (Exception exception)

            {

                //Log

            }

        }

 

        private static string CreateDirectory(AttachmentFileModel attachmentFileModel, FtpClient client)

        {

            string extension;

            if (attachmentFileModel.HttpPostedFileBase != null)

            {

                extension = Path.GetExtension(attachmentFileModel.HttpPostedFileBase.FileName);

            }

            else

            {

                extension = attachmentFileModel.FileName;

            }

 

            extension = extension.Replace(".", "");

            var path = string.Format("FolderName-" + extension + "/");

            if (!client.DirectoryExists(path))

                client.CreateDirectory(path);

            return path;

        }

    }

 

As I insinuated, this is a distilled helper and basic usage of CRUD on FTP, you can change it based on your needs as I have done many times. Cheers!



Handling custom error in mvc

In asp.net MVC there is a custom error in web.config like below:

<customErrors mode="On">

<error statusCode="404" redirect="~/404.html"/>

</customErrors>

 

Sometimes you want to redirect the user to your own custom error controller and log the error message. You can handle it! Firstly create your own Error controller:

 

public class ErrorController : Controller

    {

        public ActionResult HttpError404()

        {

            return View("HttpError404");

        }



        public ActionResult HttpError500()

        {

            return View("HttpError500");

        }



        public ActionResult General()

        {

            return View("General");

        }

    }

 

Secondly, you need to handle this controller in a higher level in your application, refer to global.asax and create the Application_Error method with the following definition:

protected void Application_Error(object sender, EventArgs e)

        {

            Exception exception = Server.GetLastError();        

            Response.Clear();

            HttpException httpException = exception as HttpException;

            RouteData routeData = new RouteData();

            routeData.Values.Add("controller", "Error");



            if (httpException != null)

            {

                switch (httpException.GetHttpCode())

                {

                    case 404:

                        routeData.Values.Add("action", "HttpError404");

                        break;

                    case 500:

                        routeData.Values.Add("action", "HttpError500");

                        break;

                    default:

                        routeData.Values.Add("action", "General");

                        break;

                }

            }



            routeData.Values.Add("error", exception);

            Server.ClearError();

            Response.TrySkipIisCustomErrors = true;

            IController errorController = new ErrorController();

            errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));

        }

 

Done! Now you can create your own Views of ErrorController and have your handled ErrorController.



About Me

Ehsan Ghanbari

Hi! my name is Ehsan. I'm a developer, passionate technologist, and fan of clean code. I'm interested in enterprise and large-scale applications architecture and design patterns and I'm spending a lot of my time on architecture subject. Since 2008, I've been as a developer for companies and organizations and I've been focusing on Microsoft ecosystem all the time. During the&nb Read More

Post Tags
Pending Blog Posts
Strategic design
Factory Pattern
time out pattern in ajax
Selectors in Jquery
Peridic pattern
How to query over Icollection<> of a type with linq
How to use PagedList In asp.net MVC
Domain driven design VS model driven architecture
What's the DDD-lite?
Fluent Nhibernate Sample Project in Asp.net MVC