…meie igapäevast IT’d anna meile igapäev…

2016-01-20

Adding a service reference to ASP.NET vNext/ASP.NET Core 1.0

Recently I started a new project in ASP.NET vNext aka ASP.NET 5, or as it is known since yesterday, ASP.NET Core 1.0. Since right now the framework is still in RC stage, there is next to no documentation to speak of… but that is a topic for another day.

But I had to add several WCF service references to the project to communicate with the back-end server. While we used to have a reasonably nice dialog for service references, it no longer exists in VS 2015 for ASP.NET Core 1.0. However – there is a plugin for adding “Connected services”, read about it at http://blogs.msdn.com/b/webdev/archive/2015/12/15/wcf-connected-service-visual-studio-extension-preview-for-asp-net-5-projects.aspx.

And I cannot stress this enough – while this plugin is in preview/current stage, do not use it. It is not capable of re-using code in referenced assemblies, which means it generates new classes instead of re-using old ones – and it cannot re-create generic classes. E.g. Response<User> becomes ResponseOfUserFq_SrmLzS, which is really not what is expected or wanted.

Instead, use good old svcutil from command line (you should probably create a cmd file, since you’ll probably want to update the service reference repeatedly):

svcutil.exe /l:cs /t:code /n:*,Your.Project.Desired.NameSpace /r:"fullpath-to-dto-assembly.dll" /r:"fullpath-to-model-assembly.dll" /r:"fullpath-to-vendor-assembly.dll" /o:Reference.cs http://localhost:9000/SomeServices/OurService.svc?fullwsdl

This will fetch the service info and create the service client (Reference.cs) and output.config while re-using all of the classes from assemblies specified with the /r keys. /n key allows you to specify the namespace for the generated code.

Note that the code generated with svcutil will require full .NET framework, not just .NET Core 1.0.

After I had figured out all of the above, I put my service configuration to wwwroot\web.config and expected it to work.

Nope. Enpoint configuration not found. No matter what I did, I could not get my development server (Kestrel) to read the <system.serviceModel> wwwroot\web.config. However, invalid XML in there gave an instant error… explain that?!

Googling was not all that helpful. There seems to be no way for ASP.NET Core to read service configuration from JSON files. But then I stumbled upon a lead – release announcement for ASP.NET 5 beta 7 had a single line announcing support of app.config when running on a full .NET framework.

And this is what I needed to do – instead of using good ol’ web.config (oh, how I hate thee!), you have to create an app.config in the root folder of your website (not wwwroot!), same place where project.json lives. You can just move the output.config there and rename it to app.config – and System.ServiceModel will now happily read the configuration from there.

Advertisements

2012-04-20

XSS protection: encode all class string properties easily

Filed under: ASP.NET MVC,Programmeerimine — Sander @ 11:58:40
Tags: , , ,

CSharpLogo

Protecting your web applications against XSS or cross-site scripting should be a no-brainer for web programmers. The vulnerability is well-known and understood.

And yet, by far the majority of website security vulnerabilities are XSS-related. Either we forget to strip the tags, or whitelist the tags, or encode the string – or in many cases, deem it as an unnecessary precaution.

Don’t do the latter. Always minimize the attack surface, even if you’re doing an intranet web application for six users. There is no such thing as an application or website that is completely secure, but that is what we should aim for, even though the goal is impossible.

To help with encoding, I created a helper class that will automatically help to encode/whitelist/strip the tags from all writeable string properties from a class, be it DTO, viewmodel, entity from EF or elsewhere. Note that this is NOT a complete solution – you need to decide which type of protection to implement, see the newValue variable. Tag whitelist or wholesale HttpUtility.HtmlEncode() are probably your best bets (I’ll try do an article about HTML tag whitelisting next week).

I also encourage you to extend and improve my solution, as there are great many things that could be added – such as allowing for specific XSS protection for different fields (using an attribute, for example), encoding of string in arrays/lists/dictionaries, to work with fields and private properties and so forth.

HtmlEncoder has just one method – EncodeHtml() – with two signatures. You can specify which properties to exclude from XSS protection, ie. say you have a DTO class of a comment – with string properties such as Content, Email, Name, Website and Signature. You want to allow limited HTML in the signature and content, so you don’t want them to be completely encoded and therefore need to exclude them.

Use:
  • HtmlEncoder.EncodeHtml(myCommentDto); if you want all of the string properties to be affected.
  • HtmlEncoder.EncodeHtml(myCommentDto, x => x.Content, x => x.Signature); – exclude Content and Signature using lambda expressions. This is the preferred method of excluding properties, as the compiler will catch typos or property name changes. You will not get an error, if you add a non-string property by accident.
  • HtmlEncoder.EncodeHtml(myCommentDto, "Content", "Signature"); – exclude Content and Signature specifying the property names as strings. Note that typos or property name changes mean that the property will still be encoded. You may even want to declare this method private, so other programmers will not be able to use it and introduce subtle, hard to find bugs.

And here is the class. Happy encoding!

  1. /// <summary>
  2. /// Helper to escape HTML in all string fields of a class.
  3. /// </summary>
  4. public static class HtmlEncoder
  5. {
  6.     /// <summary>
  7.     /// Encodes the HTML in all writeable public string properties, which are not included into excludedProperties expressions
  8.     /// Use: HtmlEncoder.EncodeHtml(comment, x => x.CommentBody, x => x.SomeOtherProperty, x => x.CreatedBy, x => x.CreatedDate);
  9.     /// or: HtmlEncoder.EncodeHtml(comment); if you don't need to exclude any fields
  10.     /// Non-string properties will not be affected and no error is thrown if you include them to the excluded properties
  11.     /// All values of the excluded string properties will not be changed
  12.     /// </summary>
  13.     /// <typeparam name="TEntity">The type of the entity.</typeparam>
  14.     /// <param name="entity">The entity.</param>
  15.     /// <param name="excludedProperties">The excluded properties.</param>
  16.     public static void EncodeHtml<TEntity>(TEntity entity, params Expression<Func<TEntity, object>>[] excludedProperties) where TEntity : class
  17.     {
  18.         EncodeHtml(entity, GetExcludedStringPropertyNames(excludedProperties).ToArray());
  19.     }
  20.  
  21.     /// <summary>
  22.     /// Encodes the HTML in all writeable public string properties, which are not included into excludedProperties
  23.     /// Use: HtmlEncoder.EncodeHtml(comment, "CommentBody", "SomeOtherProperty", "CreatedBy")
  24.     /// All values of the excluded string properties will not be changed
  25.     /// </summary>
  26.     /// <typeparam name="TEntity"></typeparam>
  27.     /// <param name="entity"></param>
  28.     /// <param name="excludedProperties"></param>
  29.     public static void EncodeHtml<TEntity>(TEntity entity, params string[] excludedProperties) where TEntity : class
  30.     {
  31.         var stringProperties = typeof(TEntity).GetProperties(BindingFlags.Instance | BindingFlags.SetProperty | BindingFlags.Public)
  32.             .Where(x => x.PropertyType == typeof(string) && !excludedProperties.Contains(x.Name)).ToList();
  33.  
  34.         foreach (var propertyInfo in stringProperties)
  35.         {
  36.             var value = (string)propertyInfo.GetValue(entity, null);
  37.  
  38.             if (!string.IsNullOrWhiteSpace(value))
  39.             {
  40.                 //Apply here a suitable method of encoding – replace, wholesale HtmlEncode(), tag whitelisting or something else
  41.  
  42.                 var newValue = value.Replace('<', ' ').Replace('>', ' ');
  43.                 //var newValue = HttpUtility.HtmlEncode(value);
  44.  
  45.  
  46.                 propertyInfo.SetValue(entity, newValue, null);
  47.             }
  48.         }
  49.     }
  50.  
  51.     /// <summary>
  52.     /// Get from expressions only writeable string property names, so we know what to exclude.
  53.     /// </summary>
  54.     /// <typeparam name="TEntity"></typeparam>
  55.     /// <param name="expressions"></param>
  56.     /// <returns></returns>
  57.     private static List<string> GetExcludedStringPropertyNames<TEntity>(params Expression<Func<TEntity, object>>[] expressions)
  58.     {
  59.         var propertyNames = new List<string>(expressions.Length);
  60.  
  61.         //this can be completely LINQ, but is way easier to debug and understand as foreach
  62.         foreach (var expression in expressions)
  63.         {
  64.             if (expression.Body.NodeType == ExpressionType.MemberAccess)
  65.             {
  66.                 var memberExpression = (MemberExpression)expression.Body;
  67.                 var info = memberExpression.Member as PropertyInfo;
  68.                 if (info != null && info.CanWrite && info.PropertyType == typeof(string))
  69.                 {
  70.                     propertyNames.Add(memberExpression.Member.Name);
  71.                 }
  72.             }
  73.         }
  74.         return propertyNames;
  75.     }

2011-06-27

ASP.NET MVC: Simple checkbox extension

Filed under: ASP.NET MVC — Sander @ 13:41:00
Tags: ,

As you may or may not have noticed, ASP.NET MVC checkbox implementation is just bad. In addition of regular <input type="checkbox".. it will render secondary hidden input, ” so that an unselected check box will return false”. This is supposed “make it easy to bind to view data or model data”. Considering how forums are full of people asking why their checkboxes misbehave, I’d say it is fairly safe to claim they failed.

I got tired of writing <input type=”checkbox” name=”mycheckbox” id=”mycheckbox” /> every time I needed a “normal”, checkbox, so I wrote a set SimpleTextbox extensions for InputExtensions (Html.SimpleTextbox()):

public static class SimpleCheckboxHelper
{
  public static MvcHtmlString SimpleCheckbox(this HtmlHelper helper, string name)
  {
    return SimpleCheckbox(helper, name, false, null);
  }

  public static MvcHtmlString SimpleCheckbox(this HtmlHelper helper, string name, bool @checked)
  {
    return SimpleCheckbox(helper, name, @checked, null);
  }

  public static MvcHtmlString SimpleCheckbox(this HtmlHelper helper, string name, bool @checked, object htmlAttributes)
  {
    return SimpleCheckbox(helper, name, @checked, new RouteValueDictionary(htmlAttributes));
  }

  public static MvcHtmlString SimpleCheckbox(this HtmlHelper helper, string name, bool @checked, IDictionary<String, Object> htmlAttributes)
  {
    string attributes = string.Empty;
    if (htmlAttributes != null && htmlAttributes.Count > 0)
      attributes = htmlAttributes.Aggregate(attributes, (current, htmlAttribute) => current + string.Format(" {0}=\"{1}\"", htmlAttribute.Key, htmlAttribute.Value));

    var s = string.Format("<input type=\"checkbox\" name=\"{0}\" id=\"{0}\"{1}{2}/>", name, @checked ? " checked=\"checked\"" : string.Empty, attributes);
    return new MvcHtmlString(s);
  }
}

(code formatted with http://quickhighlighter.com/code-syntax-highlighter.php, as I cannot currently use my normal utilities)

Using SimpleCheckbox is same as using normal ASP.NET MVC checkbox:

  • @Html.SimpleCheckbox(“Active”) – renders normal checkbox, not checked.
  • @Html.SimpleCheckbox(“Active”, Model.Active) – checked if Model.Active is true, unchecked if not.
  • @Html.SimpleCheckbox(“Active”, Model.Active, new { @class = “mycheckboxclass” }) – adds CSS class (or other attributes) to the checkbox.
Järgmine lehekülg »

Create a free website or blog at WordPress.com.