<commit_before>﻿using System;
using System.ComponentModel.DataAnnotations;
using System.Net;
using System.Reflection;
using System.Web.Mvc;
using Sdl.Web.Common.Logging;
using Sdl.Web.Common.Models;

namespace Sdl.Web.Mvc.Controllers
{
    public class EntityController : BaseController
    {
        /// <summary>
        /// Renders an Entity Model
        /// </summary>
        /// <param name="entity">The entity model</param>
        /// <param name="containerSize">The size (in grid units) of the container the entity is in</param>
        /// <returns>Rendered entity model</returns>
        [HandleSectionError(View = "SectionError")]
        public virtual ActionResult Entity(EntityModel entity, int containerSize = 0)
        {
            SetupViewData(entity, containerSize);

            ViewModel model = EnrichModel(entity);
            if (model is RedirectModel)
            {
                // Force a redirect (ASP.NET MVC doesn't allow child actions to redirect using RedirectResult)
                Response.StatusCode = (int) HttpStatusCode.Redirect;
                Response.RedirectLocation = ((RedirectModel) model).RedirectUrl;
                Response.End();
            }

            return View(model.MvcData.ViewName, model);
        }

        /// <summary>
        /// Maps Form data (for an HTTP POST request) to properies of a given Entity Model and performs basic validation.
        /// </summary>
        /// <param name="model">The Entity Model to map the form data to.</param>
        /// <returns><c>true</c> if there is any form data to be mapped.</returns>
        protected bool MapRequestFormData(EntityModel model)
        {
            if (Request.HttpMethod != "POST")
            {
                return false;
            }

            Type modelType = model.GetType();
            foreach (string formField in Request.Form)
            {
                PropertyInfo modelProperty = modelType.GetProperty(formField);
                if (modelProperty == null)
                {
                    Log.Debug("Model [{0}] has no property for form field '{1}'", model, formField);
                    continue;
                }

                string formFieldValue = Request.Form[formField];

                RequiredAttribute requiredAttr = modelProperty.GetCustomAttribute<RequiredAttribute>();
                if (requiredAttr != null && string.IsNullOrEmpty(formFieldValue))
                {
                    Log.Debug("Required property '{0}' has no value in form data.");
                    string errorMessage = requiredAttr.ErrorMessage ?? string.Format("Field '{0}' must be specified.", formField);
                    ModelState.AddModelError(formField, errorMessage);
                    continue;
                }

                try
                {
                    modelProperty.SetValue(model, Convert.ChangeType(formFieldValue, modelProperty.PropertyType));
                }
                catch (Exception ex)
                {<commit_msg>TSI-66 Improved form data mapping (TSI-1954)<commit_after>﻿using System;
using System.ComponentModel.DataAnnotations;
using System.Net;
using System.Reflection;
using System.Web.Mvc;
using Sdl.Web.Common.Logging;
using Sdl.Web.Common.Models;

namespace Sdl.Web.Mvc.Controllers
{
    public class EntityController : BaseController
    {
        /// <summary>
        /// Renders an Entity Model
        /// </summary>
        /// <param name="entity">The entity model</param>
        /// <param name="containerSize">The size (in grid units) of the container the entity is in</param>
        /// <returns>Rendered entity model</returns>
        [HandleSectionError(View = "SectionError")]
        public virtual ActionResult Entity(EntityModel entity, int containerSize = 0)
        {
            SetupViewData(entity, containerSize);

            ViewModel model = EnrichModel(entity);
            if (model is RedirectModel)
            {
                // Force a redirect (ASP.NET MVC doesn't allow child actions to redirect using RedirectResult)
                Response.StatusCode = (int) HttpStatusCode.Redirect;
                Response.RedirectLocation = ((RedirectModel) model).RedirectUrl;
                Response.End();
            }

            return View(model.MvcData.ViewName, model);
        }

        /// <summary>
        /// Maps Form data (for an HTTP POST request) to properies of a given Entity Model and performs basic validation.
        /// </summary>
        /// <param name="model">The Entity Model to map the form data to.</param>
        /// <returns><c>true</c> if there is any form data to be mapped.</returns>
        protected bool MapRequestFormData(EntityModel model)
        {
            if (Request.HttpMethod != "POST")
            {
                return false;
            }

            Type modelType = model.GetType();
            foreach (string formField in Request.Form)
            {
                if (formField == "__RequestVerificationToken")
                {
                    // This is not a form field, but the Anti Request Forgery Token
                    continue;
                }

                PropertyInfo modelProperty = modelType.GetProperty(formField);
                if (modelProperty == null)
                {
                    Log.Debug("Model [{0}] has no property for form field '{1}'", model, formField);
                    continue;
                }

                string formFieldValue = Request.Form[formField];

                RequiredAttribute requiredAttr = modelProperty.GetCustomAttribute<RequiredAttribute>();
                if (requiredAttr != null && string.IsNullOrEmpty(formFieldValue))
                {
                    Log.Debug("Required property '{0}' has no value in form data.");
                    string errorMessage = requiredAttr.ErrorMessage ?? string.Format("Field '{0}' must be specified.", formField);
                    ModelState.AddModelError(formField, errorMessage);
                    continue;
                }

                try
                {
                    if (modelProperty.PropertyType == typeof (bool))
                    {
                        // The @Html.CheckBoxFor method includes a hidden field with the original checkbox state, resulting in two boolean values (comma separated)
                        formFieldValue = formFieldValue.Split(',')[0];
                    }
                    modelProperty.SetValue(model, Convert.ChangeType(formFieldValue, modelProperty.PropertyType));
                }
                catch (Exception ex)
                {
{'fraction_non_alphanumeric': 0.09477959981946743, 'fraction_numerical': 0.0025575447570332483, 'mean_word_length': 1.7630922693266833, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3737388', 'n_tokens_mistral': 1593, 'n_tokens_neox': 1512, 'n_words': 450}