using System; using System.Collections.Generic; using System.Web.Mvc; using Portoa.Web.Util; namespace VideoGameQuotes.Web.Models { public class ApiModel { public ApiModel() { Criteria = new Dictionary>(); } public bool FetchAll { get; set; } public int Id { get; set; } public SortMethod SortMethod { get; set; } public SortOrder SortOrder { get; set; } public IDictionary> Criteria { get; set; } } public class ApiModelBinder : IModelBinder { public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { var model = new ApiModel { SortMethod = SortMethod.None, SortOrder = SortOrder.Ascending }; ParseId(controllerContext, model); ParseSort(controllerContext, model); ParseCriteria(controllerContext, model); return model; } private static void ParseCriteria(ControllerContext controllerContext, ApiModel model) { var criteria = (controllerContext.RouteData.Values["criteria"] ?? string.Empty).ToString().Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); for (var i = 0; i < criteria.Length; i++) { switch (criteria[i]) { default: if (i < criteria.Length - 1) { model.Criteria[criteria[i]] = ParseCommaSeparatedCriterion(criteria[i + 1]); i++; } else { controllerContext.AddModelError("criteria", "Unable to parse criteria for key \"system\""); } break; } } } private static IEnumerable ParseCommaSeparatedCriterion(string csv) { var values = csv.Split(','); var results = new List(); foreach (var value in values) { int result; if (int.TryParse(value, out result)) { results.Add(result); } else { results.Add(value); } } return results; } private static void ParseSort(ControllerContext controllerContext, ApiModel model) { var sortValue = controllerContext.HttpContext.Request.QueryString["sort"]; if (string.IsNullOrWhiteSpace(sortValue)) { return; } var sortValues = sortValue.Split('|'); try { model.SortMethod = (SortMethod)Enum.Parse(typeof(SortMethod), sortValues[0], ignoreCase: true); } catch { controllerContext.AddModelError("sort", string.Format("The sort method \"{0}\" is invalid", sortValues[0])); } if (sortValues.Length > 1) { try { model.SortOrder = (SortOrder)Enum.Parse(typeof(SortOrder), sortValues[1], ignoreCase: true); } catch { controllerContext.AddModelError("sort", string.Format("The sort order \"{0}\" is invalid", sortValues[1])); } } } private static void ParseId(ControllerContext controllerContext, ApiModel model) { var idValue = (controllerContext.RouteData.Values["id"] ?? string.Empty).ToString(); int id; if (int.TryParse(idValue, out id)) { if (id <= 0) { controllerContext.AddModelError("id", "Invalid value for id"); } else { model.Id = id; } } else { model.FetchAll = idValue == "all"; } } } }