Wednesday, 4 December 2013

AutoMapper



What's it?
A library to help reducing the time you spend on object-object mappings. E.g. from a Business Entity to a Data Transfer Object (DTO).

Considerations?
  • Always remember to create unit tests for your mappings to make sure AutoMapper works as you expect because it can be tricky when there are associations and complex objects and it might not behave as you'd expect.
Create the Map:

Mapper.CreateMap();

Perform the Map Between Two Objects

OrderDto dto = Mapper.Map(order);

Where to Create the Maps?

Create a Bootstrapper class and call it from the global.ascx; once per application.

Automatic Mapping Rules

Flattening:
  • order.Name <=> orderDto.Name
  • order.Customer.Name <=> orderDto.CustomerName
  • order.GetTotal() => orderDto.Total
Projection:
Mapper.CreateMap()
   .ForMember(dest => dest.EventDate, opt => opt.MapFrom(src => src.Date.Date))
Ignore a Property Mapping:
Mapper.CreateMap()
  .ForMember(dest => dest.SomeValuefff, opt => opt.Ignore());






Wednesday, 18 September 2013

Set Max Length on an HTML TextArea Control

  var limit = 10;

  $(document).ready(function(){

    $('textarea').keypress(function()
    {
      return $(this).val().length < limit;
    });

              $('textarea').keyup(function(){
     
                  var text = $(this).val();
 
                   if(text.length > limit){
     
                    $(this).val(text.substr(0,limit));
                 }  
              })
  });

Actually the best option perhaps would be using this jquery plugin: http://jqueryvalidation.org/

Friday, 30 August 2013

Distributed Application Frameworks

Primary purpose: "Distributed and asyncronous processing using Publish/Subscribe Communication model".

NService Bus:
Mass Transit:
Queues:
  • MSMQ
  • Amazon Queue
  • SQL Server Queue
Saga:
  • A long running process usually used to handle the life cycle of a certain parent message


Wednesday, 14 August 2013

Oracle

Oracle Data Access Components (ODAC) for Oracle Client: 
http://www.oracle.com/technetwork/database/windows/downloads/index-101290.html

Installing above will enable you to connect to an Oracle Server from your PC. It installs all the required data access components, etc as well as the Oracle Client.

Friday, 2 August 2013

Security Threats of Internet Applications

Cross-Site Scripting (CSS)

An attacker can inject some client-side scripts to application servers so that when users request certain web pages, they also receive other contents. Pretty significant security risk for application servers.

It can lead to stolen cookies and manipulated pages. Stolen cookies mean the attacker can logon to the target website on behalf of you!

Example:

  • The attacker sends an email to the user containing a link to the vulnerable site on which the user has an account.
  • Once the link is clicked, the malicious script in returned from the vulnerable site and gets executed in the user's browser.
  • The script sends the user session cookie to the attacker.
  • The attacker can access the site user account and do whatever he/she desires!

https://en.wikipedia.org/wiki/Cross-site_scripting

How to prevent?

  • https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet
  • Set all cookies as HTTPOnly
  • https://www.owasp.org/index.php/XSS
  • XSS
https://www.owasp.org/index.php/DOM_based_XSS_Prevention_Cheat_Sheet

Open Redirection Attacks

1. An attacker sends a malicious email to website users or (simply putting a malicious link online) asking users to logon with the below genuine Dashboard Logon Page but redirecting to the forged page
2. https://www.MIS.com/Dashboard/LogOn?ReturnUrl=https%3A%2F%2Fwww.MIIS.com/Dashboard
3. The user logins but Dashboard redirects them to the external forged site
4. Note that the malicious site has an extra “i” so users won’t notice it as it’ll look exactly like the genuine Dashboard site (that’s super easy to create; just save page as!)
5. This forged page includes an error message requesting that user logins again. User might think they have mistyped their password.
6. Our username/password get saved by the forged site
7. Then they redirect us back to the genuine Dashboard site as normal
8. So the end result is that the attacker has stolen the user credentials silently without even user noticing it


Other Security Concerns:

  • XSS Attacks (Cross Site Scripting)
    • XSS Phishing
    • XSS Stored Attacks
    • XSS Reflected Attacks
  • CSRF Attacks (Cross Site Request Forgery)
  • XST Attacks (Cross Site Tracing)
  • Cross-Server Attacks
  • Concurrency
  • SQL Injection; perhaps not relevant to us
  • SSL
  • Invalidated input controls

Security Firms:

  • https://www.qualys.com/
  • https://www.gdssecurity.com/
  • https://www.checkmarx.com/
  • http://www.pentest.co.uk/
Standards:

Thursday, 25 July 2013

NHibernate

NHibernate Pitfalls: http://weblogs.asp.net/ricardoperes/archive/2011/06/17/nhibernate-pitfalls-index.aspx

Wednesday, 17 July 2013

Web API Formatters

     public static class FormattersConfig
    {
        public static void Register(HttpConfiguration config)
        {
            #region Json Formatter

            // Default formatter is Json Formatter
            // Default Json Formatter uses Json.Net
            // You can change the Json Formatter to use DataContractJsonSerializer
            config.Formatters.JsonFormatter.UseDataContractJsonSerializer = true;

            // How to Remove?
            config.Formatters.Remove(config.Formatters.JsonFormatter);

            #endregion

             #region Xml Formatter

            // Default Xml Formatter uses DataContractSerializer
            // You can change the Xml Formatter to XmlSerializer
            config.Formatters.XmlFormatter.UseXmlSerializer = true; 

            // How to Remove?
            config.Formatters.Remove(config.Formatters.XmlFormatter);

            #endregion

            #region Custom Formatter, custom Xml, comma delimited values, etc

            // Create CustomFormatter class which extends MediaTypeFormatter class.
            // Then call config.Formatters.Add(new CustomFormatter());
            // http://serena-yeoh.blogspot.co.uk/2013/02/aspnet-web-api-custom-formatter.html#!/2013/02/aspnet-web-api-custom-formatter.html

            #endregion
        }

Friday, 12 July 2013

AngularJS

You can access the presentation at: http://prezi.com/hzn2dxxwhdr2/angular-presentation/?utm_campaign=share&utm_medium=copy



The Screencast is at: http://www.youtube.com/watch?v=eXHPmbAFiiw



You should be able to run https://github.com/mflerin/angularjs-basics on your pc without any problems (this is the code that accompanies the screencast)



The rest of the source code is at: https://github.com/mflerin/node-angular-infrastructure this requires mongodb and nodejs to run. You can install these on your pc but it requires a bit of work.



Friday, 5 July 2013

Web API and Tracing

We wrote our custom request/response logger for our Web API project so that we can analyze and monitor all the inputs and outputs whereas there seems to be a built-in tracing feature in the Web API:

http://blogs.msdn.com/b/roncain/archive/2012/04/12/tracing-in-asp-net-web-api.aspx

I'll try it for my next Web API project!

Tuesday, 2 July 2013

How to control the Request Size and Execution Timeout


Limiting the Request

You can apply the below limits on the request:

  • Request size; default is 28.6MB in IIS 7.0 and 4MB in IIS 6.0. Please see below.
  • Request header size
  • Url length; default is 4KB
  • Query string length; default is 2KB
http://www.iis.net/configreference/system.webserver/security/requestfiltering/requestlimits

Request Size

If content size exceeds 1024 bytes then throw 404.13 error:


  
    
      
        
          
            
          
        
      
    
  



IIS 6.0:


  
    
    
    
  



IIS 7.0:

  
    
      
      
      
    
  




Request TimeOut


  
  
  




  
    
  




Max Response Size

• Response size by default doesn’t have a limit from the server point of view.

• The client, however, can limit the response size by setting “content-length” in the request header.

• If very large data required, we should be considering compressing the data or returning binary data. How large is very large?! Perhaps above 50MB.

Sunday, 23 June 2013

Web API POST

http://stackoverflow.com/questions/11142702/aspnet-webapi-post-parameter-is-null-when-sending-xml
http://forums.asp.net/t/1787686.aspx/1
  • Add Content Type:
  • User-Agent: Fiddler
  • Content-Type: application/xml (this is for the server)
  • Accept: application/xml (this is for the client)
  • For DataContractSerializer, add the namespace to the root of the posted data or remove namespace from the DataContract:

Tuesday, 7 May 2013

How to Select a Web API Controller at Runtime?

You can implement IHttpControllerSelector interface and select a controller at runtime.

You may want to do this when you're supporting multiple versions of the API for backward compatibility.

The version number might be in the header or in the url e.g. api/v1/events/1.


using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;
using System.Linq;

namespace WebApiSecurityDemo.Model.Versioning
{
    public class VersionControllerSelector : DefaultHttpControllerSelector
    {
        private readonly HttpConfiguration _configuration;

        private Dictionary _apiControllerTypes;

        private const string ApiContainerAssembly = "WebApiSecurityDemo.WebApi";

        public VersionControllerSelector(HttpConfiguration configuration)
            : base(configuration)
        {
            _configuration = configuration;
            this.VersionLocation = VersionLocationStrategy.FromUrl;
        }

        private Dictionary ApiControllerTypes
        {
            get
            {
                return _apiControllerTypes ?? (_apiControllerTypes = GetControllerTypes());
            }
        }

        public enum VersionLocationStrategy
        {
            FromUrl,
            FromHeader
        }

        public VersionLocationStrategy VersionLocation { get; set; }
        
        public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
        {                
            return GetVersionedController(request) ?? base.SelectController(request);
        }

        private HttpControllerDescriptor GetVersionedController(HttpRequestMessage request)
        {
            var controllerName = base.GetControllerName(request);

            var version = ExtractVersion(request);
        
            if (version == null)
            {
                // throw bad request - version is compulsory
                return null;
            }

            var type = GetControllerTypeByVersion(version, controllerName);

            if (type == null)
            {
                // throw bad request - not supported
                return null;
            }

            return new HttpControllerDescriptor(_configuration, controllerName, type);
        }

        private string ExtractVersion(HttpRequestMessage request)
        {
            return this.VersionLocation == VersionLocationStrategy.FromUrl
                ? ExtractVersionFromUrl(request)
                : ExtractVersionFromHeader(request);
        }

        private static string ExtractVersionFromUrl(HttpRequestMessage request)
        {
            Match match = Regex.Match(request.RequestUri.PathAndQuery, @"/v(?\d+)/", RegexOptions.IgnoreCase);

            return match.Success ? match.Groups["version"].Value : null;
        }

        private static string ExtractVersionFromHeader(HttpRequestMessage request)
        {
            var version = request.Headers.Accept.Select(i => i.Parameters.Single(s => s.Name == "version").Value).ToList();

            return !version.Any() ? null : version.First();
        }

        private Type GetControllerTypeByVersion(string version, string controllerName)
        {
            var versionToFind = string.Format("V{0}", version.ToLower());

            var controllerNameToFind = string.Format("{0}.{1}{2}", versionToFind, controllerName, ControllerSuffix);

            return ApiControllerTypes.Where(t => t.Key.ToLower().Contains(versionToFind.ToLower())
                                                 && t.Key.EndsWith(controllerNameToFind, StringComparison.OrdinalIgnoreCase)).Select(t => t.Value).FirstOrDefault();
        }

        private static Dictionary GetControllerTypes()
        {
            var apiAssembly = AppDomain.CurrentDomain.GetAssemblies().Single(a => a.FullName.Contains(ApiContainerAssembly));

            return apiAssembly
                .GetTypes()
                .Where(t => !t.IsAbstract && t.Name.EndsWith(ControllerSuffix) && typeof(IHttpController).IsAssignableFrom(t))
                .ToDictionary(thisType => thisType.FullName);
        }
    }
}


then you can register the new ControllerSelector:
GlobalConfiguration.Configuration.Services.Replace(typeof (IHttpControllerSelector), new VersionControllerSelector(GlobalConfiguration.Configuration));


Wednesday, 24 April 2013

How to Use XmlAttribute with a Nullable Type?

Imagine you have the below property which should be serialized as an xml attribute if it has value and if not, it should just be ignored from the serialization:
[XmlAttribute("lastUpdated")]
public DateTime? LastUpdated { get; set; }
The solution would be introducing a new property and a new method:
 [XmlIgnore]
        public DateTime? LastUpdated { get; set; }

        [XmlAttribute("lastUpdated")]
        public DateTime LastUpdatedSerializable
        {
            get { return this.LastUpdated.Value; }
            set { this.LastUpdated = value; }
        }

        public bool ShouldSerializeLastUpdatedSerializable()
        {
            return LastUpdated.HasValue;
        }
It's important to know that ShouldSerialize{Property} and {Property}Specified are .NET Conventions to resolve this issue. I liked to find a better/cleaner/simpler approach but haven't found any yet.

Friday, 19 April 2013

How to Post a Request to a Web API Web Service?

My test Web API Method looks like this:

 [HttpPost]
        public HttpResponseMessage TestPost(string siteName, User user, string providerName)
        {
            var result = string.Format("sitename is {0}. user is {1}. providername is {2}", 
                siteName,
                user == null 
                ? "null. " 
                : " not null; " + (string.Format("email: {0}, pass: {1}", user.EmailAddress, user.Password)),
                providerName);

            return new HttpResponseMessage()
                {
                    Content = new StringContent(result)
                };
        }

If I had started the naming with "Post" then I didn't need to use "HttpPost" attribute; by convention it could have found it automatically.

How to write the Route Template?

 config.Routes.MapHttpRoute(
             name: "testpost",
             routeTemplate: "sites/{siteName}/User/TestPost/{providerName}",
             defaults: new
             {
                 controller = "User",
                 action = "TestPost",
                 providerName = UrlParameter.Optional
             });

As shown, the last parameter is optional so it accepts the below sample urls:

 http://www.domain.com/sites/sitename1/user/TestPost/provider1 http://www.domain.com/sites/sitename1/user/TestPost

Also, the {siteName} value is automatically mapped to the siteName input parameter of the web method.

As you can see, I don't put the User object in to the url template since it will be posted and not visible in the get.

How to Make Post Calls?
Now, I've written two test methods showing two approaches to make Post Calls to this service. First approach is easier and uses RestSharp and the second approach uses WebRequest.

.NET 4.5 provides a new class called HttpClient which makes it even easier to make such calls.

 [TestClass]
    public class WhenLoadingAUser
    {
        private readonly string _baseUrlForLuis = ConfigurationManager.AppSettings["BaseUrlFor.Luis"];
        
        /// 
        /// Approach 1 using RestSharp
        /// 
        [TestMethod]
        public void Should_post_successfully_with_valid_userDetailsList_usingRestSharp()
        {
            // arrange
            string url = string.Format("{0}/sites/{1}/User/TestPost/viper", this._baseUrlForLuis,
                "viper");

            var client = new RestClient(url);
            
            var request = new RestRequest(Method.POST)
                {
                    RequestFormat = DataFormat.Xml
                };


            // When reaches the Web Service, the below anonymous object gets mapped to the User object automatically.
            request.AddObject(new
                {
                    EmailAddress = "emailAddreess",
                    Password = "some password"
                });

            // act
            var response = client.Execute(request).Content;
        }

        /// 
        /// Approach 2 using WebRequest
        /// 
        [TestMethod]
        public void Should_post_successfully_with_valid_userDetailsList_usingWebRequest()
        {
            // arrange
            string url = string.Format("{0}/sites/{1}/User/TestPost/viper", this._baseUrlForLuis,
                "viper");

            var httpWReq = (HttpWebRequest)WebRequest.Create(url);
            httpWReq.Method = "POST";
            httpWReq.ContentType = "application/x-www-form-urlencoded";
            
            // not sure why the below format is required and not xml 
            string postData = "EmailAddress=email&Password=pass";

            // act
            PostData(httpWReq, postData);
            string response = GetResponseAsString(httpWReq);
        }

        private static string GetResponseAsString(HttpWebRequest httpWReq)
        {
            var response = (HttpWebResponse) httpWReq.GetResponse();

            return  new StreamReader(response.GetResponseStream()).ReadToEnd();
        }

        private static void PostData(HttpWebRequest httpWReq, string postData)
        {
            var encoding = new ASCIIEncoding();

            byte[] data = encoding.GetBytes(postData);

            httpWReq.ContentLength = data.Length;

            using (Stream stream = httpWReq.GetRequestStream())
            {
                stream.Write(data, 0, data.Length);
            }
        }
    }


How to make the post call with Fiddler?

The Content-Type header is important. Also, the data which is sent should be prepended with "=".



How to make a Post Call with just with a browser?

  1. Open a page that you know has the JQuery library; e.g. www.jquery.com 
  2. Click F12 and go to the Console tab where you can write JQuery codes
  3. Type "$.post('your url here',{'':'your data here'});

Monday, 15 April 2013

Amazon Simple Storage Services (S3)


Understanding Amazon S3 is very simple, believe me! It’s just like a Windows Folder on the cloud/internet and you can put files and folders in it!

It also enables you to add meta-data for each folder and file.

The root folder is called Bucket and you can have multiple buckets inside which you can have folders, subfolders or any type of file stored.

There are few other features as well.

How to view the Amazon S3 Folders/Buckets?

There are 3 ways you can work with Amazon S3 and view the folders and files:

Useful Links:

Blue Green Deployment Environments

The idea is that we should be having two copies (Blue and Green) of the same application on each environment (Dev, Staging, Live, etc).

One environment is always passive and is where we deploy the changes to and can test and make sure that all the tests pass e.g. blue.app

The other environment is always active which is an old passive application which has been activated after the tests have all passed.


Monday, 4 March 2013

Using Microsoft Bing Maps Geocode Service

Geocode Service

Details:
http://msdn.microsoft.com/en-us/library/cc966793.aspx

Purpose:
Allows you to find a geolocation of an address.

Keys:
http://www.microsoft.com/maps/

C# sample for using the Geocode Service:
http://msdn.microsoft.com/en-GB/library/cc966817.aspx