tag:blogger.com,1999:blog-14732665178599752872024-03-13T11:20:42.555-07:00A learning journeyA learning journeyAnonymoushttp://www.blogger.com/profile/07593060906502313590noreply@blogger.comBlogger16125tag:blogger.com,1999:blog-1473266517859975287.post-92145518200321051492013-12-05T11:52:00.000-08:002013-12-11T10:00:57.826-08:00Html.RatingFor: Extending the MVC HtmlHelperWhen working on a web application, I was in the need to add a rating for a product. That rating will be between 1 and 5 and will be always an int. So my model has a property like <code>public int Rating {get;set;}</code>. I decided to add 5 radio buttons, and each will hold the corresponding rating value.
<br />
<br />
But then (as always happen) the requirement changed. We didn't want to have only 1 rating property, but 5. So adding 5 radios for each was something that I didn't want to happen
<br />
<br />
In order to solve this problem, I created an <strong>extension method</strong> for the <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.htmlhelper(v=vs.118).aspx" rel="nofollow" target="_blank">HtmlHelper</a> class that we normally use in our MVC applications. As you may notice, in the method I created all the logic for adding the set of radio buttons needed for the rating process.
<br />
<br />
<pre class="brush:csharp">
public static MvcHtmlString RatingFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, int from, int to, object htmlAttributes = null)
{
var builder = new StringBuilder();
var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
var model = metadata.Model;
var name = ExpressionHelper.GetExpressionText(expression);
var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
var fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
int direction = 1;
if (from > to)
direction = -1;
for (var i = from; direction == 1 ? i <= to : i >= to; i += direction)
{
var tagBuilder = new TagBuilder("input");
tagBuilder.MergeAttributes(attributes);
tagBuilder.MergeAttribute("type", "radio");
tagBuilder.MergeAttribute("name", fullName, true);
tagBuilder.MergeAttribute("value", i.ToString(CultureInfo.InvariantCulture));
//If model has a value we need to select it
if (model != null && model.Equals(i))
{
tagBuilder.MergeAttribute("checked", "checked");
}
tagBuilder.GenerateId(fullName);
ModelState modelState;
if (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out modelState))
{
if (modelState.Errors.Count > 0)
{
tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
}
}
tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(name, metadata));
builder.AppendLine(tagBuilder.ToString(TagRenderMode.SelfClosing));
}
return MvcHtmlString.Create(builder.ToString());
}
</pre>
<br />
One important part of this code is
<br />
<pre class="brush:csharp">if (model != null && model.Equals(i))
{
tagBuilder.MergeAttribute("checked", "checked");
}
</pre>
<br />
where we assign the value of the property if it is already set. This is useful when you use this method on an Edit process.
<br />
<br />
Now on your view, instead of having to create all that radio buttons manually, you can have something like this
<br />
<pre class="brush:csharp">@Html.RatingFor(model => model.Rating, 1, 5)
</pre>
in order to add a rating from 1 to 5.
<br />
<br />
Hopefully you will find this useful. If you have created another useful helper, it would be nice if you share it with the community :)
<br />
<div>
<a href="http://www.codeproject.com/script/Articles/BlogFeedList.aspx?amid=pollirrata" rel="tag" style="display: none;">CodeProject</a>
</div>Anonymoushttp://www.blogger.com/profile/07593060906502313590noreply@blogger.com0tag:blogger.com,1999:blog-1473266517859975287.post-69817910780351368542013-11-29T19:05:00.000-08:002013-11-29T22:37:36.662-08:00Public field not bound when posting to WebAPI (or a deep dive into WebAPI model binding)When trying to create a sandbox project using WebAPI (on MVC4), I was struggling with a weird problem: My data wasn't being received in the server. I had the following jQuery call
<br />
<pre class="brush:javascript">$.post("api/Values", {value1:1, value2:2}, function(result){ console.log(result); })
</pre>
and the WebAPI service action that I was targeting was something like this
<br />
<pre class="brush:csharp">public IEnumerable<string> Post(Dummy value)
{
return new string[] { value.Value1, value.Value2 };
}
</string></pre>
I noticed that even that the instance of Dummy was being created, <code>Value1</code> and <code>Value2</code> where always null. The Dummy class was
<br />
<pre class="brush:csharp">public class Dummy
{
public string Value1;
public string Value2;
}
</pre>
Pretty simple, right?. Well, after reading doing a lot of research, I changed by accident one of the <code>Dummy</code> fields to become a property
<br />
<pre class="brush:csharp">public class Dummy
{
public string Value1;
public string Value2 {get;set;}
}
</pre>
I tested again and <em>Voilà!!</em>... well, half voilà actually... When posting, now I was receiving data in <code>Value2</code>, but still not in Value1. This was really intriguing... how come property was being assigned correctly but not the field? Both are public, right? Why the difference?
<br />
Obviously, I knew the solution was changing both fields to be properties now, but I wanted to know <strong>why</strong> was that happening. I started digging on how WebAPI works and found a really interesting <a href="http://www.asp.net/posters/web-api/asp.net-web-api-poster.pdf" rel="nofollow" target="_blank">Web API poster</a>, that describes the full lifecycle of a HTTP message. There I got my first clue, so I started researching on how ModelBinding happens. As described there, one of the binding methods is MediaTypeFormatter. Since I was sending JSON object, I tested the Deserialization process based on the test methods provided in the <a href="http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization" rel="nofollow" target="_blank">WebAPI overview site</a>
<br />
<pre class="brush:csharp">T Deserialize<t>(MediaTypeFormatter formatter, string str) where T : class
{
// Write the serialized string to a memory stream.
Stream stream = new MemoryStream();
StreamWriter writer = new StreamWriter(stream);
writer.Write(str);
writer.Flush();
stream.Position = 0;
// Deserialize to an object of type T
return formatter.ReadFromStreamAsync(typeof(T), stream, null, null).Result as T;
}
</t></pre>
passing the same JSON object that I had on my jQuery call. The result: The method assigned successfully the values for both the field and the property. By inspecting the HTTP Request headers, I found out that data wasn't being actually sent as JSON but in the following format: <code>Content-Type:application/x-www-form-urlencoded; charset=UTF-8</code>, which tells the server that data is being sent like this: <code>Value1=1&Value2=2</code>. Then, we need to change the AJAX call to be like this
<br />
<pre class="brush:javascript">$.ajax({
url: "api/Values",
data: JSON.stringify({Value1:1,Value2:2}),
type: "POST",
contentType:"application/json; charset=utf-8"
})
</pre>
please notice 2 things: I changed the contentType for the request <strong>AND</strong> Stringified the JSON object. By doing these changes, <code>Dummy</code> public fields were now populated correctly.
<br />
Now, I still wanted to know why my values weren't bound when I wasn't specifying the request content type. Doing more research, I found this really interesting article by Mike Stall called <a href="http://blogs.msdn.com/b/jmstall/archive/2012/04/16/how-webapi-does-parameter-binding.aspx" rel="nofollow" target="_blank">How WebAPI does parameter binding</a> which states
<br />
<blockquote>
There are 2 techniques for binding parameters: Model Binding and Formatters. In practice, WebAPI uses model binding to read from the query string and Formatters to read from the body
</blockquote>
If you are not yet bored, you might remember that when we didn't specify the request content type, the data was being sent as <code>Content-Type:application/<strong>x-www-form-urlencoded</strong>; charset=UTF-8</code>. This means, that WebAPI was using ModelBinding (and not formatters) to populate the <code>Dummy</code> instance. Moreover, <a href="http://blogs.msdn.com/b/jmstall/archive/2012/04/16/how-webapi-does-parameter-binding.aspx" rel="nofollow" target="_blank">the article</a> has another interesting declaration:
<br />
<blockquote>
ModelBinding is the same concept as in MVC, [...]. Basically, there are “ValueProviders” which supply pieces of data such as query string parameters, and then a model binder assembles those pieces into an object.
</blockquote>
And how does ModelBinding work in MVC? That was my next question. And I was really happy that Microsoft open-sourced the ASP.Net WebStack, because there is where we can find the answer. If we look into <a href="http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/DefaultModelBinder.cs" rel="nofollow" target="_blank">DefaultModelBinder source code</a>, we'll find that when talking about complex models, <strong>it only looks for the object properties</strong> to populate the data (maybe because having public fields is a bad practice).
<br />
Well, I hope you can find this post as interesting as I found learning all this. Some times making silly errors can drive you into learn really interesting things.
<br />
<h2>
Useful references</h2>
<br />
<ul>
<li><a href="http://blogs.msdn.com/b/jmstall/archive/2012/04/16/how-webapi-does-parameter-binding.aspx" rel="nofollow" target="_blank">http://blogs.msdn.com/b/jmstall/archive/2012/04/16/how-webapi-does-parameter-binding.aspx</a></li>
<li><a href="http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api" rel="nofollow" target="_blank">http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api </a></li>
<li><a href="http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization" rel="nofollow" target="_blank">http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization</a></li>
<li><a href="http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters" rel="nofollow" target="_blank">http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters</a></li>
<li><a href="http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/DefaultModelBinder.cs" rel="nofollow" target="_blank">http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/DefaultModelBinder.cs</a></li>
<li><a href="http://api.jquery.com/jQuery.ajax/" rel="nofollow" target="_blank">http://api.jquery.com/jQuery.ajax/</a></li>
</ul>
<a href="http://www.codeproject.com/script/Articles/BlogFeedList.aspx?amid=pollirrata" rel="tag" style="display: none;">CodeProject</a>Anonymoushttp://www.blogger.com/profile/07593060906502313590noreply@blogger.com0tag:blogger.com,1999:blog-1473266517859975287.post-71309608522276525302013-11-19T15:29:00.001-08:002013-11-20T09:50:29.226-08:00Backing field for automatically implemented property [Field] must be fully assigned before control is returned to the callerWorking with structs in C# gives you a lot of flexibility on the way you design your applications, but since they are not reference types, they have some special features that we need to take in count.<br />
Recently I was working on a web application and I created a struct to hold a pair of values that is being used very frequently. It is something like this
<pre class="brush:csharp">
public struct StringTuple{
public string Value1 {get; set;}
public string Value2 {get; set;}
}
</pre>
After some code changes, I decided that it would be a good option to have a constructor to pass the struct values
<pre class="brush:csharp">
public struct StringTuple
{
public StringTuple(string value1, string value2)
{
Value1 = value1;
Value2 = value2;
}
public string Value1 { get; set; }
public string Value2 { get; set; }
}
</pre>
but the compiler started complaining, giving me the following error
<blockquote>
Backing field for automatically implemented property Value1 must be fully assigned before control is returned to the caller
</blockquote>
It was the first time that I had seen that error, so after some time of think and research I remembered one of the basic principles of working with structs: <strong>members are initialized when the default constructor is called</strong>. That is why creating a new constructor was creating a problem, since we were overloading the constructor call and skipping that member initialization
<h1>The solution</h1>
Since the problem is that we're not calling the default constructor, the solution is obviously call it, so we just need to add that call to the constructor that we just introduced.
<pre class="brush:csharp">
public struct StringTuple
{
public StringTuple(string value1, string value2):this()
{
Value1 = value1;
Value2 = value2;
}
public string Value1 { get; set; }
public string Value2 { get; set; }
}
</pre>
By that, the error message is gone and we can continue happily working with structs
<a href="http://www.codeproject.com/script/Articles/BlogFeedList.aspx?amid=pollirrata" rel="tag" style="display: none;">CodeProject</a>Anonymoushttp://www.blogger.com/profile/07593060906502313590noreply@blogger.com0tag:blogger.com,1999:blog-1473266517859975287.post-10134877819095732022013-05-13T19:35:00.001-07:002013-05-13T19:40:53.964-07:00Install XAMPP on a Ubuntu 13.04 virtual machine running on Windows Azure One of the many great things about Windows Azure is how easy you can create a virtual machine, no matter the OS of your preference. But for good or bad, your virtual machine will be fresh, so you need to work on setting up whatever you need to get to work.<br />
<br />
Recently I needed to set up some web applications that I preferred to run on Linux, and for that I prefer to use XAMPP because of the simplicity of the installation process. But this time was not as straightforward as on my previous experiences, so then this is how I did it.<br />
<br />
I'll assume that you already have the virtual machine created; I chose an Ubuntu Server 13.04 instance from the gallery. After getting the virtual machine up and running, the first step I did was to download the latest XAMPP version from the <a href="http://www.apachefriends.org/en/xampp-linux.html" rel="nofollow" target="_blank">Apache friends website</a>.<br />
<br />
<pre class="brush:bash">sudo wget http://sourceforge.net/projects/xampp/files/XAMPP%20Linux/1.8.1/xampp-linux-1.8.1.tar.gz/download?use_mirror=iweb&download=
</pre>
<br />
After that you need to extract the files from the tar, so we follow the process described for the XAMPP installation guide
<br />
<br />
<pre class="brush:bash">sudo tar xvfz xampp-linux-1.8.1.tar.gz -C /opt</pre>
<br />
So far, so good. But when we try to start our XAMPP server using
<br />
<br />
<pre class="brush:bash">sudo /opt/lampp/lampp start</pre>
<br />
We get the following error
<br />
<br />
<pre>XAMPP is currently only availably as 32 bit application. Please use a 32 bit compatibility library for your system.
</pre>
<pre>
</pre>
To solve this, there are 2 posible solutions, both of them start by doing
<br />
<br />
<pre class="brush:bash">sudo apt-get update</pre>
<br />
After this, you can install the <code>ia32-lib package</code>
<br />
<code><br /></code>
<pre class="brush:bash">sudo apt-get install ia32-lib </pre>
<br />
This solution worked for me on previous Ubuntu versions, but not this time. If this solution doesn't work for you either, then you need to run the following command
<br />
<br />
<pre class="brush:bash">sudo dpkg --add-architecture i386 && sudo apt-get update && sudo apt-get install ia32-libs</pre>
<br />
As stated in this <a href="http://askubuntu.com/questions/219465/cannot-install-ia32-lib-package/221215#221215">askubuntu.com answer</a>,
<br />
<blockquote>
(...) installing through WUBI did not correctly detect the available foreign architectures. As tumbleweed suggested printing the foreign architectures probably returns nothing. Add i386 as a foreign architecture, update the apt cache, then install the 32 bit libs.
</blockquote>
So then now you might be able to start your XAMPP server by
<br />
<br />
<pre class="brush:bash">sudo /opt/lampp/lampp start</pre>
<br />
You should now get something like this
<br />
<br />
<pre>Starting XAMPP 1.8.1...
LAMPP: Starting Apache...
LAMPP: Starting MySQL...
LAMPP started.
</pre>
<pre>
</pre>
With this you have successfully installed your XAMPP server, the next step is to test your web server. When you create a new virtual machine, by default the only open port is the one designed for SSH. In order to access the server via a different port we need to create a new <b>endpoint</b>. On the Virtual Machine administration page, go to the endpoints tab
<br />
<br />
<center>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGbJAdkwUB8ur5FFtNj7lbP_EhsoPEnmIdWF9Rt-t5M6pGjANanN6YZljtFAhUjj35b8cHpB5_SelTJwlBXpDZtT7ut7GuSAwcijMOkFIX-ZaLiKnsOPIwiu9ttOMlyHiD5IjWIgpk4-U/s1600/2013-05-13+13_06_21-Virtual+machines+-+Windows+Azure.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGbJAdkwUB8ur5FFtNj7lbP_EhsoPEnmIdWF9Rt-t5M6pGjANanN6YZljtFAhUjj35b8cHpB5_SelTJwlBXpDZtT7ut7GuSAwcijMOkFIX-ZaLiKnsOPIwiu9ttOMlyHiD5IjWIgpk4-U/s320/2013-05-13+13_06_21-Virtual+machines+-+Windows+Azure.png" /></a>
</center>
<center>
<br /></center>
<br />
There you will see the list of the endpoints that we already have. If it is a new VM you might see only the one corresponding to SSH.
<br />
<br />
Click on <small>ADD ENDPOINT</small> button at the bottom of the page, and you will see the small window to create a new endpoint.
<br />
<br />
<center>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiulmVCKgm8GB_vc1FJLpJKErlupvAtLkQRZGWZZqv99YzBX0AGl6jn1677j0E_smL-N-CRNoJRuPmkuQqatBbMgIX7XdxwGGTLhdOSPabslUdUKXa_uRFC7JtuQCCDqc75xJoAWSjZcxs/s1600/2013-05-13+13_14_11-Virtual+machines+-+Windows+Azure.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiulmVCKgm8GB_vc1FJLpJKErlupvAtLkQRZGWZZqv99YzBX0AGl6jn1677j0E_smL-N-CRNoJRuPmkuQqatBbMgIX7XdxwGGTLhdOSPabslUdUKXa_uRFC7JtuQCCDqc75xJoAWSjZcxs/s320/2013-05-13+13_14_11-Virtual+machines+-+Windows+Azure.png" /></a>
</center>
<br />
<br />
Click on Next button and you will see the window to specify the endpoint data
<br />
<br />
<center>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihv1B6p-vUxjgQESEiue57IiTzTawB0UDsB1ejz9uS4erDAiELigYpcZilelheScC_VtWDkpwvo3Y3DcxBVQa8rHiGfnIOgfN2VcOF9-oCCAWh2U0lpXT9yEBnqhQDLS86vqlaFtWhgmQ/s1600/2013-05-13+13_15_22-Virtual+machines+-+Windows+Azure.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihv1B6p-vUxjgQESEiue57IiTzTawB0UDsB1ejz9uS4erDAiELigYpcZilelheScC_VtWDkpwvo3Y3DcxBVQa8rHiGfnIOgfN2VcOF9-oCCAWh2U0lpXT9yEBnqhQDLS86vqlaFtWhgmQ/s320/2013-05-13+13_15_22-Virtual+machines+-+Windows+Azure.png" /></a>
</center>
<br />
You can choose the name you want but it cannot be the same as an existing one; the protocol will be TCP. The public port is the one you will use to access your webserver, so it can be anything you want. The private port is the one your XAMPP server is using to serve the content. It is normally the 80, but you can change that on the XAMPP configuration accordingly to your needs.
<br />
<br />
After clicking the complete button, you should be able to see your new endpoint listed and now you can access your web server from any part in the world with something like this
<br />
<br />
<pre>http://[youthostname].cloudapp.net:[yourpublicport]
</pre>
<br />
Once the page loads, you will most likely see the following error message<br />
<br />
<pre>New XAMPP security concept:
Access to the requested object is only available from the local network.
This setting can be configured in the file "httpd-xampp.conf".
If you think this is a server error, please contact the webmaster.
</pre>
<br />
So then what you need to do is modify the specified file. According to our installation, it will be located in <code>/opt/lampp/etc/extra/</code> directory. We need to find the section with the title "New XAMPP security concept" and comment out the full <code>LocationMatch</code> section or adjust the values of the allowed IP addresses if you don't want to open your site to the public.<br />
<br />
Another change we need to make in the same file is on the <code>Directory "/opt/lampp/phpmyadmin"</code> section. We need to add there <code>Requiere all granted </code> to be able to access the phpMyAdmin site. Remember to add some IP filters so it is not open to anybody that has the URL address to access it.<br />
<br />
To finish, just restart your XAMPP server<br />
<br />
<pre class="brush:bash">sudo /opt/lampp/lampp restart
</pre>
<br />
And voilà, you are now ready to work with your XAMPP server on the cloud.
<a href="http://www.codeproject.com/script/Articles/BlogFeedList.aspx?amid=pollirrata" rel="tag" style="display: none;">CodeProject</a>Anonymoushttp://www.blogger.com/profile/07593060906502313590noreply@blogger.com1tag:blogger.com,1999:blog-1473266517859975287.post-22786477220015493102013-04-03T14:44:00.000-07:002013-04-11T12:44:23.714-07:00Localize your MVC app based on a subdomainHaving an application in multiple languages is now a requirement in many projects. In ASP.net, you can tell your application that the language that should be using corresponds to the one the browser is specifying. While this is a really nice feature in the ideal scenarios (since the user gets the applications in the proper language automatically), there are some scenarios where this might be not the expected behavior like:<br />
<ul>
<li>If your user's computer locale is different than the one he or she prefers for using your application (like when he or she is using a different computer than his/her own)</li>
<li>When the browser settings have been modified to some value diferent than whatever the user prefers and he or she does not have the knowledge to adjust this setting on the browser.</li>
</ul>
<div>
In these cases, the user would rather to have a "fallback" mechanism so he or she can select his/her preferred language. One of the options you can use to achieve this is selecting the language/locale based on a subdomain. By this, you will give the users the following options:<br />
<br /></div>
<div>
<table align="center" cellspacing="10">
<tbody>
<tr>
<th>Desired language</th>
<th>URL address</th>
</tr>
<tr>
<td>English</td>
<td>en.myapp.com</td>
</tr>
<tr>
<td>Spanish</td>
<td>sp.myapp.com</td>
</tr>
<tr>
<td>Finnish</td>
<td>fi.myapp.com</td>
</tr>
</tbody></table>
<br /></div>
<div>
In order to support this, you will need to create an <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.actionfilterattribute(v=vs.108).aspx" target="_blank">ActionFilterAttribute</a>, something like this<br />
<pre class="brush:csharp">public class LocalizationFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var locales = new Dictionary<string string="">();
locales.Add("mx", "es-MX");
locales.Add("sp", "es-ES");
locales.Add("vi", "vi-VN");
locales.Add("fi", "fi-FI");
var subdomain = GetSubDomain();
if (subdomain != string.Empty && locales.ContainsKey(subdomain))
{
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(locales[subdomain]);
Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(locales[subdomain]);
HttpContext.Current.Response.Write(String.Format("Culture: {0}", Thread.CurrentThread.CurrentCulture.Name));
}
else
{
HttpContext.Current.Response.Write("Culture: Default ");
}
base.OnActionExecuting(filterContext);
}
private string GetSubDomain()
{
var url = HttpContext.Current.Request.Headers["HOST"];
var index = url.IndexOf(".");
if (index < 0)
{
return string.Empty;
}
var subdomain = url.Split('.')[0];
if (subdomain == "www" || subdomain == "localhost")
{
return string.Empty;
}
return subdomain;
}
}
</string></pre>
<br />
As you may already noticed, with this code you define a list of locales that will be selected according to the provided subdomain. The next step would be registering this filter so it is used in all the views. You can do this in your Global.asax file<br />
<br />
<pre class="brush:csharp">public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new LocalizationFilterAttribute());
filters.Add(new HandleErrorAttribute());
}
</pre>
<br />
Once you have a way to set the locale for the current thread, all you need to do is the localization process, which can be done as you already have it. In my case, I'm using resource files to have all the translations and have a fallback resource file if any requested text has no translation on any of the language-specific resource files.</div>
<div>
<br />
By this, you can provide your users a simple and easy-to-remember way to get your application in their desired language.</div>
<a style="display:none;" href="http://www.codeproject.com/script/Articles/BlogFeedList.aspx?amid=pollirrata" rel="tag">CodeProject</a>Anonymoushttp://www.blogger.com/profile/07593060906502313590noreply@blogger.com2tag:blogger.com,1999:blog-1473266517859975287.post-26104753056170252332013-03-05T07:59:00.000-08:002013-04-11T12:36:05.780-07:00Runtime customizable model attributes in ASP.net MVC3<div id="section_1">
It can be because you want to implement I18N without the use of resources, or your model classes are outside of your MVC project, or any other reason you have that make you want not being tied to the inline (compile time) annotations on your model.</div>
<div id="section_1">
<br /></div>
<div id="section_1">
Whatever is the case, you can solve this by creating a custom class that help you to add these annotations dinamically. In this case, will be working on adding some validations defined on an XML file.<br />
<h2>
Create the CustomValidationProvider class</h2>
</div>
<div id="section_1">
This CustomValidationProvider class, that will inherit from <a href="http://msdn.microsoft.com/en-us/library/system.web.mvc.dataannotationsmodelvalidatorprovider(v=vs.100).aspx">DataAnnotationsModelValidatorProvider</a>, and it will help you adding all the validations that you need in the view accordingly.</div>
<div id="section_1">
<br />
<br />
<pre class="brush:csharp">public class CustomValidationProvider{
private readonly string _validationsFile = "";
public ConventionModelValidatorProvider(string validationsFile)
{
_validationsFile = validationsFile;
}
}
</pre>
<br />
<br />
When creating the instance of ConventionValidatorProvider, it needs to receive the name of the xml that will be used to load the validations. This instance is created in Global.asax file<br />
<br /></div>
<pre class="brush:csharp">ModelValidatorProviders.Providers.Clear();
ModelValidatorProviders.Providers.Add(
new CustomValidationProvider(ConfigurationManager.AppSettings.Get("validationsFile"))
);
</pre>
<div id="section_2">
It is important to notice that first we clear all the ModelValidatorProviders, in order to remove the one that comes with ASP.NET MVC by default.<br />
<div style="margin-right: 1.5em; margin-top: 1.5em;">
<h2>
Validations XML</h2>
As we said earlier, we will define the validations for our models in an xml file. This XML file has the following structure
<br />
<pre class="brush:xml"><elements>
<models>
<model name="HomeViewModel">
<property name="OrganizationId">
<validations>
<validation errormessage="Please provide the Internal Organization" type="Required">
<!--[More validations ...]-->
</validation></validations>
</property>
<!--[More properties ...]-->
</model>
</models>
<!--[More models ...]-->
</elements>
</pre>
<br />
<br />
In this structure we define the models and properties that will be validated. For each defined property one or more validations need to exist; these are the types that we will be using for this example <br />
<br />
<pre class="brush:xml"><validation type="Required" errorMessage="The product description is required" />
</pre>
The field will be requierd and if not provided, the value on errorMessage attribute will be displayed<br />
<br />
<pre class="brush:xml"><validation type="StringLengthAttribute" min="5" max="10" errorMessage = "5-10 characters" />
</pre>
The field will be treated as string and its length value needs to be greater or equal than value specified on min attribute and lower or equal to value specified in max atribute, otherwise the value on errorMessage attribute will be displayed<br />
<br />
<pre class="brush:xml"><validation type="RangeAttribute" min="5" max="10" errorMessage = "specify something between 5 and 10" /></pre>
The field will be treated as numeric and its value needs to be greater or equal than value specified on min attribute and lower or equal to value specified in max atribute, otherwise the value on errorMessage attribute will be displayed</div>
</div>
<div id="section_3">
<div style="background-color: white; font-family: Verdana, sans-serif; font-size: 14px;">
</div>
<br />
<pre class="brush:xml"><validation type="RegularExpressionAttribute" errorMessage = "Code should start with 0x and be followed by only digits or A-F letters">
<regex>
<![CDATA[
[0][x][0-9a-fA-F]+
]]>
</regex>
</validation>
</pre>
The field will be tested against the specified regular expression; if it does not comply with the regex, the value on errorMessage attribute will be displayed<br />
<div>
<h2>
Adding the validations to the page</h2>
<div>
Every time a view is loaded, the GetValidators method from the ModelValidator class is called for each propety that we have in the form. By this, all the needed validations are added to the list that will be used by MVC to determine which fields have a specific constraint that needs to be satisfied before saving. </div>
<div>
<br /></div>
<div>
That said, we need then to create our own implementation of the GetValidators method by overriding whatever the base class have right now:</div>
<div>
<br /></div>
<div>
<div>
<pre class="brush:csharp">
protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
</pre>
</div>
<div>
</div>
</div>
<div>
<br /></div>
<div>
Before we go further, there are 4 important elements that we need to identify when this method is executed:<br />
<br />
1. Action that it's being executed<br />
<pre class="brush:csharp">context.Controller.ControllerContext.RouteData.Values["action"].ToString();
</pre>
<br />
<br />
2. Controller where this Action exists<br />
<pre class="brush:csharp">context.Controller.ControllerContext.RouteData.Values["controller"].ToString();
</pre>
<br />
<br />
3. Property that is being checked if will be validated or not<br />
<pre class="brush:csharp">metadata.PropertyName
</pre>
<br />
<br />
4. Model (class) where that property exists<br />
<pre class="brush:csharp">metadata.ContainerType.Name
</pre>
<br />
<br />
Once we know this elements, the rest is only read the XML file to determine if the the type and quantity of validations that the current property needs. In order to keep this post as clean as possible, I'll ommit the code that is used to read the XML file. If you need information on how to do that, you can check <a href="http://support.microsoft.com/kb/307548" rel="nofollow" target="_blank">this article</a> or have a look on <a href="http://msdn.microsoft.com/en-us/library/bb387098.aspx" rel="nofollow" target="_blank"> LinqToXML</a>.<br />
<br />
<br />
We need to filter the XML file that we previously defined to get the validations for the property of the model that is being checked. If at least on validation exists, we start looping on the list and we create the validations using a sort of simple factory. Each validation is created with the counterpart class defined on <a href="http://msdn.microsoft.com/en-us/library/cc490428(v=vs.100).aspx">System.ComponentModel.DataAnnotations</a> Namespace. In this example we're only defining a few validation types. You can define more if needed.</div>
<pre class="brush:csharp">switch (validationType)
{
case "Required":
attr = new RequiredAttribute();
break;
case "StringLengthAttribute":
var attribute1 = validation.Attribute("max");
var xAttribute2 = validation.Attribute("max");
if (xAttribute2 != null)
{
int max = int.Parse(attribute1 != null && String.IsNullOrEmpty(attribute1.Value)
? "0"
: xAttribute2.Value);
var attribute2 = validation.Attribute("min");
var xAttribute3 = validation.Attribute("min");
if (xAttribute3 != null)
{
int min = int.Parse(attribute2 != null && String.IsNullOrEmpty(attribute2.Value)
? "0"
: xAttribute3.Value);
attr = new StringLengthAttribute(max);
((StringLengthAttribute)attr).MinimumLength = min;
}
}
break;
case "RegularExpressionAttribute":
var regex = validation.Descendants().Single(a => a.Name == "regex").Value.Trim();
attr = new RegularExpressionAttribute(regex);
break;
case "RangeAttribute":
var attribute3 = validation.Attribute("max");
var xAttribute4 = validation.Attribute("max");
if (xAttribute4 != null)
{
double rangeMax = double.Parse(attribute3 != null && String.IsNullOrEmpty(attribute3.Value)
? "0"
: xAttribute4.Value);
var attribute2 = validation.Attribute("min");
var xAttribute3 = validation.Attribute("min");
if (xAttribute3 != null)
{
double rangeMin = double.Parse(attribute2 != null && String.IsNullOrEmpty(attribute2.Value)
? "0"
: xAttribute3.Value);
attr = new RangeAttribute(rangeMin, rangeMax);
}
}
break;
case "DataTypeAttribute":
attr = new DataTypeAttribute(String.IsNullOrEmpty(attribute.Value)
? ""
: attribute.Value);
break;
}
</pre>
<div>
<div style="background-color: white; font-family: Verdana, sans-serif; font-size: 14px;">
</div>
<div style="background-color: white; font-family: Verdana, sans-serif; font-size: 14px;">
</div>
<br />
The attribute instance that is created corresponds to the validation that will be performed on screen for that property. Each validation has its own instance, and we store each instance that we create in a list of <code>List<Attribute></code> type. Once we're done with the XML reading, the only thing we need to do is to call the base class to do the rest of the work and return the result.<br />
<pre class="brush:csharp">return base.GetValidators(metadata, context, newAttributes);</pre>
</div>
<h2>
Wrapping up</h2>
As we mentioned at the beginning of the post, using this approach you will gain a lot of flexibility on how you're adding your model validations; also, you have a reusable way to add them to your model classes no matter where they are located.</div>
</div>
<a style="display:none;" href="http://www.codeproject.com/script/Articles/BlogFeedList.aspx?amid=pollirrata" rel="tag">CodeProject</a>Anonymoushttp://www.blogger.com/profile/07593060906502313590noreply@blogger.com0tag:blogger.com,1999:blog-1473266517859975287.post-17319595553085427572013-01-31T18:34:00.000-08:002013-04-11T12:36:21.371-07:00The importance of profiling your applicationIt is well known that the ORM can help a lot in software development. In fact, they solve many problems that as developers we had in the past, specially talking about Opening and Closing Connections.
<br />
But as ORM frameworks are a powerful tool,they can also make a mess if they are not used in the proper way. Let me give you an example.
<br />
In the project I'm current working on, some users started experiencing some slowness when trying to load a page. I was assigned to investigate what was happening and propose a solution. I started by doing some profiling in the web application using <a href="http://getglimpse.com/" target="_blank">Glimpse</a>, adding some Trace messages to determine where was the problem and I noticed that the it was in a WCF service call that was taking <b>20 seconds</b> to retrieve a single record with a lot of columns (because of all the needed joins).
<br />
This was by far unacceptable, so I started to doing further profiling on the Entity Framework using <a href="http://www.hibernatingrhinos.com/products/efprof" target="_blank">Entity Framework Profiler</a>, and discovered that the slow service data was being fulfilled by a <b>4,000 lines query!</b>.<br />
I clearly understand that EF made a lot of extra and maybe unnecessary joins in order to automate the data exctraction, but, 4000 lines?! Really?!
<br />
After inspecting the long long query that EF Profiler showed me, I started noticing some duplicated <i>SELECT</i> statements. Then I went back to the service call and noticed that the code was something like this:
<br />
<pre class="brush:csharp">...
AsQueryable()
.Include("Account")
.Include("Account.Client")
.Include("Account.Client.Organization")
...
</pre>
This seemed to be good on the first look, since we wanted to get the Account, the Client of that Account, and the Organization. But what EF is understanding is that we want to get the Account, and then <b>AGAIN</b> the Account and the Client, and then <b>AGAIN</b> the Account, <b>AGAIN</b> the Client and the Organization. This then was causing that duplicated <i>SELECT</i> statements I was talking before. So to fix the problem I deleted the extra lines and the code ended up like this
<br />
<pre class="brush:csharp">...
AsQueryable()
.Include("Account.Client.Organization")
...
</pre>
and then by that, I reduced the lines of the resulting query, removed all the duplicated <i>SELECT</i> and reduced the execution time to <b>2 seconds</b>!
<br />
So, as you can see, two extra lines can screw all the work you're doing. So be careful of preventing this and do profile your applications before they go live.
<a style="display:none;" href="http://www.codeproject.com/script/Articles/BlogFeedList.aspx?amid=pollirrata" rel="tag">CodeProject</a>Anonymoushttp://www.blogger.com/profile/07593060906502313590noreply@blogger.com0tag:blogger.com,1999:blog-1473266517859975287.post-71984824951274324772012-11-15T15:26:00.001-08:002013-04-11T12:36:37.983-07:00Creating CodeCollaborator reviews using command lineSome months ago, I started using CodeCollaborator to create code reviews and ensure our developments have the desired quality.<br />
<br />
We are at the end of our development sprint, so I tried to create some code reviews using the CodeCollaborator GUI with no success. Aparently, one of the latest Java VM updates "broke" my client; actually because we are using an old version of CodeCollaborator client (v 4) which cannot work under the latest versions of Java.<br />
<br />
So if you run into the same problem, or just want to create your reviews using the command line follow the next steps described below. (Disclaimer: this was only tested on Windows and using SVN as source control, since that's our current development environment),<br />
<br />
<br />
<ol>
<li>Open the command line prompt</li>
<li>Go to your working copy folder, some thing like this<br />cd "C:\Folder\Folder\MyProjectWorkingCopyRoot"</li>
<li>Login into your CodeCollaboration Server<br />
<pre class="brush:php">ccolab login [ServerUrl] [UserName] [Password]
</pre>
You will get something like this
<pre class="brush:php">Connecting to Code Collaborator Server https://[your.server.url]/
Connected as: [Your name and username]
New configuration worked - saving configuration settings
Configuration key 'url' saved.
Configuration key 'user' saved.
Configuration key 'password' saved.
Configuration key 'server-proxy-host' cleared.
Configuration key 'server-proxy-port' cleared.
</pre>
</li>
<li>You can upload specific files, changelists, etc. In my case I needed upload all the changes made on an specific revision, so I needed to pass a SVN diff as a parameter<br /><pre class="brush:php">ccollab addsvndiffs new -r 27183:27190</pre>
If you look I added the parameter "new" wich means I'm creating a new review (and will be named "Untitled Review"); you can also pass the review-id if you want to add files to an existing review.
</li>
</ol>
<div>
With this, you can easily add files when creating or updating any CodeCollaborator review. For more information go to the <a href="http://support.smartbear.com/viewarticle/20496/" target="_blank">CodeCollaboration command line reference</a> </div>
<a style="display:none;" href="http://www.codeproject.com/script/Articles/BlogFeedList.aspx?amid=pollirrata" rel="tag">CodeProject</a>Anonymoushttp://www.blogger.com/profile/07593060906502313590noreply@blogger.com0tag:blogger.com,1999:blog-1473266517859975287.post-8911086057755440352012-11-06T00:30:00.000-08:002012-11-08T12:15:56.845-08:00Overcome to Windows Azure free trial cancellation by adding a new planI decided to <a href="http://pollirrata.blogspot.com/2012/08/updates-to-tic-tac-r-now-it-works-on.html" target="_blank">try Windows Azure more than 3 months ago</a>, most likely because of it's free 90-day offer. I can tell that I'm amazed on all the posibilies you have for free (Websites, Virtual machines, Mobile Services, etc.).<br />
<br />
So then, I decided I wanted to continue with the service after my trial period ended by "acquiring" a Pay-As-You-Go plan (that as the name says, you pay only what you use only if you use it, so at the time of my purchase my total was $0.00).<br />
<br />
Since I was swamped with many things at job, I didn't payed much attention on the warning e-mails saying that my account was about to expire. As it might be expected, my account was cancelled 2 weeks ago. Last week I was trying to upgrade my account, so I signed up on the <a href="https://www.windowsazure.com/en-us/pricing/purchase-options/" target="_blank">Pay-As-You-Go</a> plan but after several tries and wating days, I still wasn't able to use it to create new websites with it.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijom32sT-RnQKBISPto5ict9Knys9vMaPX5kgI-KhhCvT15mCq6PXdvA4XSID49AMpPScFxIZ-M2E352uXLf87J2AeHKasdZUYSY_FSKIgCjzEy9P4s5rEkUublSpr6kItI9Vombem5pE/s1600/disabledaccount.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="166" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijom32sT-RnQKBISPto5ict9Knys9vMaPX5kgI-KhhCvT15mCq6PXdvA4XSID49AMpPScFxIZ-M2E352uXLf87J2AeHKasdZUYSY_FSKIgCjzEy9P4s5rEkUublSpr6kItI9Vombem5pE/s400/disabledaccount.png" width="400" /></a></div>
<br />
<br />
So this is the process that you need to follow in order to be able to use your new plan in your account:<br />
<br />
<br />
<ol>
<li>Acquire a new plan (<a href="https://www.windowsazure.com/en-us/pricing/purchase-options/" target="_blank">Pay-As-You-Go, 6 or 12 month, etc.</a>)</li>
<li>Go to <a href="https://account.windowsazure.com/PreviewFeatures?wa=wsignin1.0">Preview Features</a> page and select the feature that you want to enable for your new plan, in my case I wanted to be able to create websites again</li>
<li>Click on "Try it now"</li>
<li>Select the plan you want to associate (your new plan). In this case I'm showing an example with Media Services because I already joined to the Websites preview</li>
</ol>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjD2iSthSDJ_8CT5ig86c7UFBT5rGSZ9QHG85oZHnhdiabApJgjAednfLuxMGetm0pqyiXwKI1lJ6oHJ0Qjg66bEYPTmYaGPylyeU_MKU2vaOjscS1gDHPojRpE8i_Ms6hzZlG0aT3yuMc/s1600/selectsubscription.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="361" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjD2iSthSDJ_8CT5ig86c7UFBT5rGSZ9QHG85oZHnhdiabApJgjAednfLuxMGetm0pqyiXwKI1lJ6oHJ0Qjg66bEYPTmYaGPylyeU_MKU2vaOjscS1gDHPojRpE8i_Ms6hzZlG0aT3yuMc/s640/selectsubscription.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
After completing this, you will see a label on the screen saying that the feature is active</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSX4rqtii9CUH7qgifqJk9A3ZGeLp_qxI_oELn6zIkQnPul5VeYTeoKlGqghdbWGcXGcWx0o6tKsmmiA7QBGN0_tcLOAx6wy7vzIcJg1nAwUsmqwC32jzj6Ckbbhm34y6z8j3vUsO3nR8/s1600/youreactive.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="166" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSX4rqtii9CUH7qgifqJk9A3ZGeLp_qxI_oELn6zIkQnPul5VeYTeoKlGqghdbWGcXGcWx0o6tKsmmiA7QBGN0_tcLOAx6wy7vzIcJg1nAwUsmqwC32jzj6Ckbbhm34y6z8j3vUsO3nR8/s640/youreactive.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
and you will be able to create websites (or any of the preview features that you selected) under your new plan</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyWlDi5oOKZN2rMoxk4xU784mRVCar2cQlqyEEWM-yHUm9u6OpmmBhsjOwyO1YqWm_cyhPdr9XpDksngXf6N_8y0EpUm9QRbwNiwWLGOk_4URDnqeX6dn5SYDYVqaEe0flM5KsMZS8G2I/s1600/enabledaccount.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="274" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyWlDi5oOKZN2rMoxk4xU784mRVCar2cQlqyEEWM-yHUm9u6OpmmBhsjOwyO1YqWm_cyhPdr9XpDksngXf6N_8y0EpUm9QRbwNiwWLGOk_4URDnqeX6dn5SYDYVqaEe0flM5KsMZS8G2I/s640/enabledaccount.png" width="640" /></a></div>
<div>
<br /></div>
<div>
Sadly, my previous websites remain cancelled and it doesn't seem to be possible to associate them with my new plan, or at least I couldn't find a way to edit them on the manage portal.</div>
<div>
<br /></div>
<div>
So, if possible try to avoid your account cancellation, but if that already happened, this post might help you if your plan is not shown on some items on your account.</div>
Anonymoushttp://www.blogger.com/profile/07593060906502313590noreply@blogger.com2tag:blogger.com,1999:blog-1473266517859975287.post-58140408184504438852012-11-03T09:08:00.000-07:002013-04-11T12:36:59.640-07:00Solution to: "The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable"<blockquote class="tr_bq">
<span style="background-color: #f6f8f9; color: #334242; font-family: 'Segoe UI', Arial, Helvetica, sans-serif; font-size: 12px;">The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.</span></blockquote>
<h3>
Problem description</h3>
<br />
The error quoted above happened to me after I started using <a href="http://automapper.org/" target="_blank">AutoMapper </a>on my WCF service for updating my entities. Previously, I had a "manual map" to assing the properties that I received on my data contract to the entity that I got on my context and update it. When we decided to implement <a href="http://automapper.org/" target="_blank">AutoMapper</a> on our project, my mapping code started like this:<br />
<br />
<br />
<pre class="brush:csharp">
Mapper.CreateMap<MyDataContract, MyEntity>.IgnoreAllNonExisting();
</pre>
<br />
<br />
Since all my properties were named the same on both classes, everything seemed to be easy peasy.<br />
<br />
But sadly, I started gotting the error message<br />
<blockquote class="tr_bq">
<span style="background-color: #f6f8f9; color: #334242; font-family: 'Segoe UI', Arial, Helvetica, sans-serif; font-size: 12px;">The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.</span></blockquote>
This message was driving me crazy, because of the text I was thinking that I was making something wrong with the FK relationships on the Database, or in someway the field was being passed null without being null on the contract, or somebody changed the table in someway (yeah sure, blame others :-P). After some deep look on the code (including debugging line by line all the updating process) I found the error.<br />
<br />
Since I'm copying the modified values (from DataContract to Entity) when mapping, I'm passing <b>all </b>the values from one instance to the other. This sounds OK, right? I mean, I want all my changes to be persisted on the database.<br />
<br />
Well, is not that easy. Since my contract comes from a web application, when saving there I don't have all the navigation properties. When this is the case and I just map <b>all</b>, I'm also <b>mapping and overwriting the values of this navigation properties</b>, that in this case are null on my DataContract. This makes the Entity to update the ForeignKey Columns that belong to that navigation property <b>to be null too</b>. That is why the error says that you're sending null values, because actually you are.<br />
<br />
<h3>
Solution</h3>
Since the problem is that we're mapping null navigation properties, and we actually don't need them to be updated on the Entity since they didn't changed on the Contract, we need to ignore them on the mapping definition:<br />
<br />
<pre class="brush:csharp">ForMember(dest => dest.RefundType, opt => opt.Ignore())
</pre>
<br />
<br />
So my code ended up like this<br />
<br />
<pre class="brush:c-sharp">Mapper.CreateMap<MyDataContract, MyEntity>
ForMember(dest => dest.NavigationProperty1, opt => opt.Ignore())
ForMember(dest => dest.NavigationProperty2, opt => opt.Ignore())
.IgnoreAllNonExisting();
</pre>
<br />
<br />
And voilà! the problem is solved.
<a style="display:none;" href="http://www.codeproject.com/script/Articles/BlogFeedList.aspx?amid=pollirrata" rel="tag">CodeProject</a>Anonymoushttp://www.blogger.com/profile/07593060906502313590noreply@blogger.com2tag:blogger.com,1999:blog-1473266517859975287.post-3948192510413455312012-09-27T22:04:00.000-07:002012-09-27T22:04:05.993-07:00There's no reason to be scared, anybody can code now. So just do it!!I was thinking over this days on how the development tools have evolved. I think that anybody can just start doing code now, with only some little training or just following some of the courses that exist over the Internet. I've been working on software for several years, and as I can tell that I hadn't a really hard time as the first Assembly or C coders did, things weren't as easy as they are now.<br />
<br />
Obviously, this doesn't mean that anybody can be a Programmer, even less a Software Engineer. For getting into that, I think, there are more topics that need to be covered beyond how to code or use an IDE. Concepts of data structures, memory management, networking and OS internals are really important to do the things correctly, not just doing them.<br />
<br />
But for that, there's a lot of info too. Even more, there are some schools or private institutions that offer "converting" your non-software degree onto something pretty similar to a Bachelor on Computer Sciences.<br />
<br />
Thanks to the new <a href="http://www.microsoft.com/visualstudio/eng/products/visual-studio-overview" target="_blank">Visual Studio 2012</a>, <a href="http://nuget.org/" target="_blank">Nuget</a>,<a href="http://www.asp.net/entity-framework" target="_blank"> Entity Framework</a>, <a href="http://www.asp.net/mvc" target="_blank">MVC3/4</a>, <a href="http://www.asp.net/web-api" target="_blank">WebApi</a>, etc. starting on the .net world is much more easier than it was 6 years ago. Frameworks like <a href="http://jquery.com/" target="_blank">jQuery </a>and <a href="http://yuilibrary.com/" target="_blank">YUI </a>are helping people to get into the Javascript world with much less difficulty, and the same has happened with <a href="http://cakephp.org/" target="_blank">Cake</a> for PHP and <a href="http://www.springsource.org/" target="_blank">Spring</a>/<a href="http://www.springsource.org/spring-roo" target="_blank">SpringRoo </a>on Java.<br />
<br />
So there is no reason to be scared, anybody can code now. So if you have an idea, or you've wondered if can do coding as a hobby, just do it! Maybe you have a million-dollar idea ;)<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/07593060906502313590noreply@blogger.com0tag:blogger.com,1999:blog-1473266517859975287.post-49320836696768491272012-08-28T20:10:00.002-07:002012-08-28T20:54:58.388-07:00Tic-Tac-R source codeAfter some tweaks, I'm releasing the source code of the Tic-Tac-R game. As you may find on the <a href="http://pollirrata.blogspot.com/2012/08/updates-to-tic-tac-r-now-it-works-on.html" target="_blank">previous post</a>, this game is an experiment on how to make a simple Tic-Tac-Toe game in a real-time web application using SignalR and host it on a cloud environment using Windows Azure.<br />
<br />
I hope you find it useful for learning just as I did<br />
<br />
<a href="https://github.com/pollirrata/tic-tac-r" target="_blank">Download the source code on Github</a>Anonymoushttp://www.blogger.com/profile/07593060906502313590noreply@blogger.com0tag:blogger.com,1999:blog-1473266517859975287.post-25500794001607077112012-08-22T23:00:00.001-07:002012-08-29T16:42:09.513-07:00Updates to Tic-Tac-R. Now it works on Windows Azure =)<blockquote class="tr_bq">
This is an update of my <a href="http://pollirrata.blogspot.com/2012/08/tic-tac-r-is-alive.html" target="_blank">previous post</a></blockquote>
<blockquote class="tr_bq">
Update: <a href="http://pollirrata.blogspot.com/2012/08/tic-tac-r-source-code.html" target="_blank">Post </a>with the source code of the game</blockquote>
After spending a lot of time testing and searching on the web, I wasn't able to get the Tic-Tac-R game on my Windows Azure website. I tried a lot of things and can shameless say that I was totally lost, since my application was working fine on a shared hosting environment (GoDaddy) but not on my Windows Azure.<br />
<br />
Thanks to an anonymous user that replied <a href="http://stackoverflow.com/questions/12041132/is-using-servicebus-required-when-my-signalr-app-will-be-deployed-to-windowsazur" target="_blank">my question on StackOverflow</a> I was able to know that this is a weird issue only happening there with some sort of caching by Windows Azure (neither really a bug on my app nor SignalR). The suggestion was changing enforce the transport to be Long Polling and with that the app started to work no the cloud. It is kinda little slow though, and I feel that some times the call that I make from the browser is lost, but is's maybe just my imagination... Time and more testing will give us the answer... In the meanwhile, you <a href="http://tic-tac-r.azurewebsites.net/" target="_blank">play the game</a> can be part of the beta testers of this simple game... It's free!! =P<br />
<br />
By the way, I updated <a href="http://signalr.net/" target="_blank">SignalR </a>to the just released 0.5.3 version and everything seems to keep working fine..<br />
<br />
I hope you can share your opinion regarding <a href="http://tic-tac-r.azurewebsites.net/" target="_blank">Tic-Tac-R</a>. It will be really appreciated it =)Anonymoushttp://www.blogger.com/profile/07593060906502313590noreply@blogger.com0tag:blogger.com,1999:blog-1473266517859975287.post-82669393602744940292012-08-19T09:10:00.000-07:002012-08-19T09:10:00.359-07:00Tic-Tac-R is alive! After several weeks of work (and intensive learning) I'm releasing Tic-Tac-R for beta testing.<br />
<br />
Tic-Tac-R is a little experiment of creating a traditional Tic-Tac-Toe game using <a href="http://signalr.net/" target="_blank">SignalR</a>, and it can be played <a href="http://games.tic-tac-r.pollirrata.com/" target="_blank">here</a>.<br />
<br />
On the next days I will be posting the code on GitHub, once we've done all the changes and fixes that might come from the beta testing period.<br />
<br />
So then, enjoy the game!<br />
<br />Anonymoushttp://www.blogger.com/profile/07593060906502313590noreply@blogger.com0tag:blogger.com,1999:blog-1473266517859975287.post-25469998730182486462012-08-15T22:17:00.000-07:002012-08-15T22:18:59.789-07:00HealthyHarry: A healthy version of the traditional snake game over HTML5<p>
As an experiment for learning HTML5 Canvas, I created this small game based on the popular "Snake" that many of us played on our old mobile phones (A Nokia 3320 in my case)
</p>
<p>
I deployed the game one of my Windows Azure websites and you can access it <b><a href="http://pollirrata.azurewebsites.net/games/healthyharry/">here</a></b>. Initially I was thinking of buying a hosting account on a different place, but I think the cloud is a good place for host this kind of pet projects and Windows Azure is a great option, (IMHO) for 2 things: 1) Is extremely easy to use (saying creating websites, databases, deploying, etc) 2) It is free for 90 days, which is great if you are starting on the cloud "wave". Let's see what happen when the cloud bills begin to come.
</p>
<p>
So then, enjoy the game online for at least the next 60 days (when my free account expires :P)
</p>
<p>
The source code is hosted on <b><a href="https://github.com/pollirrata/HealthyHarry">Github</a></b>. Feel free to do whatever you want with it
</p>Anonymoushttp://www.blogger.com/profile/07593060906502313590noreply@blogger.com0tag:blogger.com,1999:blog-1473266517859975287.post-51090416143089026092012-06-19T20:25:00.000-07:002013-04-11T12:37:15.560-07:00Send content to the layout using a Helper on CakePHP<blockquote>
This post is based on Robert Conner's code forCakePHP 1.x., and I made some changes to get it to work onCakePHP 2.x . The original post can be found <a href="http://bakery.cakephp.org/articles/rtconner/2007/08/28/anything_for_layout-making-html-from-the-view-available-to-the-layout" target="_blank">here</a>.
</blockquote>
Maybe some people have faced problems trying to send some content to the layout on CakePHP. By content I mean not only a simple string but a whole a piece of HTML code. To solve this, we can create a Helper on CakePHP 2.x, according to the following steps:
<h3>
1. Create the Helper</h3>
On theViews/Helpers folder, you need to create the .php file for the helper. In this case we will call it LayoutHelper.php
<pre class="brush:php">
class LayoutHelper extends AppHelper {
var $__blockName = null;
function blockStart($name) {
if (empty($name))
trigger_error('LayoutHelper::blockStart - name is a required parameter');
if (!is_null($this->__blockName))
trigger_error('LayoutHelper::blockStart - Blocks cannot overlap');
$this->__blockName = $name;
ob_start();
return null;
}
function blockEnd(&$view){
$buffer = @ob_get_contents();
@ob_end_clean();
$out = $buffer
$view->viewVars[$this->__blockName . '_for_layout'] = $out;
$this->__blockName = null
}
function output($var) {
if (isset($var) && $var != null)
echo $var;
}
}
</pre>
<h3>2. Setting up the content</h3>
For setting up the content that we want to send to the layout, we use the Helper
<pre class="brush:php">
$layout = $this->Helpers->load('Layout');
$layout->blockStart('custom_content');
</pre>
Right after this, we specify the content that will be sent to the layout
<pre class="brush:html">
<div>Custom content</div>
</pre>
and we close the block
<pre class="brush:php">
$layout->blockEnd($this);
</pre>
<h3>3. Show the content</h3>
For showing the content on the layout, we add the following
<pre class="brush:php">
$layout = $this->Helpers->load('Layout');
$layout->output($custom_content_for_layout);
</pre>
As we can see, this is really simple and also very useful when trying to customize the content on the layout according to the view we are loading
<blockquote>
I wrote this article also on <a href="http://bakery.cakephp.org/articles/pollirrata/2012/06/20/sending_content_to_the_layout_using_cake_2_x" target="_blank">The Bakery</a>
</blockquote>
<a style="display:none;" href="http://www.codeproject.com/script/Articles/BlogFeedList.aspx?amid=pollirrata" rel="tag">CodeProject</a>Anonymoushttp://www.blogger.com/profile/07593060906502313590noreply@blogger.com0