You've already forked linux-packaging-mono
284 lines
10 KiB
C#
284 lines
10 KiB
C#
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
|
|
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Web.WebPages.Scope;
|
|
|
|
namespace System.Web.Mvc
|
|
{
|
|
public class ViewContext : ControllerContext
|
|
{
|
|
private const string ClientValidationScript = @"<script type=""text/javascript"">
|
|
//<![CDATA[
|
|
if (!window.mvcClientValidationMetadata) {{ window.mvcClientValidationMetadata = []; }}
|
|
window.mvcClientValidationMetadata.push({0});
|
|
//]]>
|
|
</script>";
|
|
|
|
internal static readonly string ClientValidationKeyName = "ClientValidationEnabled";
|
|
internal static readonly string UnobtrusiveJavaScriptKeyName = "UnobtrusiveJavaScriptEnabled";
|
|
|
|
// Some values have to be stored in HttpContext.Items in order to be propagated between calls
|
|
// to RenderPartial(), RenderAction(), etc.
|
|
private static readonly object _formContextKey = new object();
|
|
private static readonly object _lastFormNumKey = new object();
|
|
|
|
private Func<IDictionary<object, object>> _scopeThunk;
|
|
private IDictionary<object, object> _transientScope;
|
|
|
|
private DynamicViewDataDictionary _dynamicViewDataDictionary;
|
|
private Func<string> _formIdGenerator;
|
|
|
|
// We need a default FormContext if the user uses html <form> instead of an MvcForm
|
|
private FormContext _defaultFormContext = new FormContext();
|
|
|
|
// parameterless constructor used for mocking
|
|
public ViewContext()
|
|
{
|
|
}
|
|
|
|
[SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Justification = "The virtual property setters are only to support mocking frameworks, in which case this constructor shouldn't be called anyway.")]
|
|
public ViewContext(ControllerContext controllerContext, IView view, ViewDataDictionary viewData, TempDataDictionary tempData, TextWriter writer)
|
|
: base(controllerContext)
|
|
{
|
|
if (controllerContext == null)
|
|
{
|
|
throw new ArgumentNullException("controllerContext");
|
|
}
|
|
if (view == null)
|
|
{
|
|
throw new ArgumentNullException("view");
|
|
}
|
|
if (viewData == null)
|
|
{
|
|
throw new ArgumentNullException("viewData");
|
|
}
|
|
if (tempData == null)
|
|
{
|
|
throw new ArgumentNullException("tempData");
|
|
}
|
|
if (writer == null)
|
|
{
|
|
throw new ArgumentNullException("writer");
|
|
}
|
|
|
|
View = view;
|
|
ViewData = viewData;
|
|
Writer = writer;
|
|
TempData = tempData;
|
|
}
|
|
|
|
public virtual bool ClientValidationEnabled
|
|
{
|
|
get { return GetClientValidationEnabled(Scope, HttpContext); }
|
|
set { SetClientValidationEnabled(value, Scope, HttpContext); }
|
|
}
|
|
|
|
public virtual FormContext FormContext
|
|
{
|
|
get
|
|
{
|
|
// Never return a null form context, this is important for validation purposes
|
|
return HttpContext.Items[_formContextKey] as FormContext ?? _defaultFormContext;
|
|
}
|
|
set { HttpContext.Items[_formContextKey] = value; }
|
|
}
|
|
|
|
internal Func<string> FormIdGenerator
|
|
{
|
|
get
|
|
{
|
|
if (_formIdGenerator == null)
|
|
{
|
|
_formIdGenerator = DefaultFormIdGenerator;
|
|
}
|
|
return _formIdGenerator;
|
|
}
|
|
set { _formIdGenerator = value; }
|
|
}
|
|
|
|
internal static Func<IDictionary<object, object>> GlobalScopeThunk { get; set; }
|
|
|
|
private IDictionary<object, object> Scope
|
|
{
|
|
get
|
|
{
|
|
if (ScopeThunk != null)
|
|
{
|
|
return ScopeThunk();
|
|
}
|
|
if (_transientScope == null)
|
|
{
|
|
_transientScope = new Dictionary<object, object>();
|
|
}
|
|
return _transientScope;
|
|
}
|
|
}
|
|
|
|
internal Func<IDictionary<object, object>> ScopeThunk
|
|
{
|
|
get { return _scopeThunk ?? GlobalScopeThunk; }
|
|
set { _scopeThunk = value; }
|
|
}
|
|
|
|
[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "The property setter is only here to support mocking this type and should not be called at runtime.")]
|
|
public virtual TempDataDictionary TempData { get; set; }
|
|
|
|
public virtual bool UnobtrusiveJavaScriptEnabled
|
|
{
|
|
get { return GetUnobtrusiveJavaScriptEnabled(Scope, HttpContext); }
|
|
set { SetUnobtrusiveJavaScriptEnabled(value, Scope, HttpContext); }
|
|
}
|
|
|
|
public virtual IView View { get; set; }
|
|
|
|
public dynamic ViewBag
|
|
{
|
|
get
|
|
{
|
|
if (_dynamicViewDataDictionary == null)
|
|
{
|
|
_dynamicViewDataDictionary = new DynamicViewDataDictionary(() => ViewData);
|
|
}
|
|
return _dynamicViewDataDictionary;
|
|
}
|
|
}
|
|
|
|
[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "The property setter is only here to support mocking this type and should not be called at runtime.")]
|
|
public virtual ViewDataDictionary ViewData { get; set; }
|
|
|
|
public virtual TextWriter Writer { get; set; }
|
|
|
|
private string DefaultFormIdGenerator()
|
|
{
|
|
int formNum = IncrementFormCount(HttpContext.Items);
|
|
return String.Format(CultureInfo.InvariantCulture, "form{0}", formNum);
|
|
}
|
|
|
|
internal static bool GetClientValidationEnabled(IDictionary<object, object> scope = null, HttpContextBase httpContext = null)
|
|
{
|
|
return ScopeCache.Get(scope, httpContext).ClientValidationEnabled;
|
|
}
|
|
|
|
internal FormContext GetFormContextForClientValidation()
|
|
{
|
|
return (ClientValidationEnabled) ? FormContext : null;
|
|
}
|
|
|
|
internal static bool GetUnobtrusiveJavaScriptEnabled(IDictionary<object, object> scope = null, HttpContextBase httpContext = null)
|
|
{
|
|
return ScopeCache.Get(scope, httpContext).UnobtrusiveJavaScriptEnabled;
|
|
}
|
|
|
|
private static int IncrementFormCount(IDictionary items)
|
|
{
|
|
object lastFormNum = items[_lastFormNumKey];
|
|
int newFormNum = (lastFormNum != null) ? ((int)lastFormNum) + 1 : 0;
|
|
items[_lastFormNumKey] = newFormNum;
|
|
return newFormNum;
|
|
}
|
|
|
|
public void OutputClientValidation()
|
|
{
|
|
FormContext formContext = GetFormContextForClientValidation();
|
|
if (formContext == null || UnobtrusiveJavaScriptEnabled)
|
|
{
|
|
return; // do nothing
|
|
}
|
|
|
|
string scriptWithCorrectNewLines = ClientValidationScript.Replace("\r\n", Environment.NewLine);
|
|
string validationJson = formContext.GetJsonValidationMetadata();
|
|
string formatted = String.Format(CultureInfo.InvariantCulture, scriptWithCorrectNewLines, validationJson);
|
|
|
|
Writer.Write(formatted);
|
|
}
|
|
|
|
internal static void SetClientValidationEnabled(bool enabled, IDictionary<object, object> scope = null, HttpContextBase httpContext = null)
|
|
{
|
|
ScopeCache.Get(scope, httpContext).ClientValidationEnabled = enabled;
|
|
}
|
|
|
|
internal static void SetUnobtrusiveJavaScriptEnabled(bool enabled, IDictionary<object, object> scope = null, HttpContextBase httpContext = null)
|
|
{
|
|
ScopeCache.Get(scope, httpContext).UnobtrusiveJavaScriptEnabled = enabled;
|
|
}
|
|
|
|
private static TValue ScopeGet<TValue>(IDictionary<object, object> scope, string name, TValue defaultValue = default(TValue))
|
|
{
|
|
object result;
|
|
if (scope.TryGetValue(name, out result))
|
|
{
|
|
return (TValue)Convert.ChangeType(result, typeof(TValue), CultureInfo.InvariantCulture);
|
|
}
|
|
return defaultValue;
|
|
}
|
|
|
|
private sealed class ScopeCache
|
|
{
|
|
private static readonly object _cacheKey = new object();
|
|
private bool _clientValidationEnabled;
|
|
private IDictionary<object, object> _scope;
|
|
private bool _unobtrusiveJavaScriptEnabled;
|
|
|
|
private ScopeCache(IDictionary<object, object> scope)
|
|
{
|
|
_scope = scope;
|
|
|
|
_clientValidationEnabled = ScopeGet(scope, ClientValidationKeyName, false);
|
|
_unobtrusiveJavaScriptEnabled = ScopeGet(scope, UnobtrusiveJavaScriptKeyName, false);
|
|
}
|
|
|
|
public bool ClientValidationEnabled
|
|
{
|
|
get { return _clientValidationEnabled; }
|
|
set
|
|
{
|
|
_clientValidationEnabled = value;
|
|
_scope[ClientValidationKeyName] = value;
|
|
}
|
|
}
|
|
|
|
public bool UnobtrusiveJavaScriptEnabled
|
|
{
|
|
get { return _unobtrusiveJavaScriptEnabled; }
|
|
set
|
|
{
|
|
_unobtrusiveJavaScriptEnabled = value;
|
|
_scope[UnobtrusiveJavaScriptKeyName] = value;
|
|
}
|
|
}
|
|
|
|
public static ScopeCache Get(IDictionary<object, object> scope, HttpContextBase httpContext)
|
|
{
|
|
if (httpContext == null && Web.HttpContext.Current != null)
|
|
{
|
|
httpContext = new HttpContextWrapper(Web.HttpContext.Current);
|
|
}
|
|
|
|
ScopeCache result = null;
|
|
scope = scope ?? ScopeStorage.CurrentScope;
|
|
|
|
if (httpContext != null)
|
|
{
|
|
result = httpContext.Items[_cacheKey] as ScopeCache;
|
|
}
|
|
|
|
if (result == null || result._scope != scope)
|
|
{
|
|
result = new ScopeCache(scope);
|
|
|
|
if (httpContext != null)
|
|
{
|
|
httpContext.Items[_cacheKey] = result;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
}
|