I'm building a WebPart for Microsoft SharePoint 2010.
Which method could I use from a static class that does the same than ResolveUrl?
Take a look at this:
http://msdn.microsoft.com/en-us/library/system.web.virtualpathutility.aspx
You could make use of the ToAbsolute or ToAppRelative methods in order to simulate the functionality
http://www.west-wind.com/weblog/posts/2007/Sep/18/ResolveUrl-without-Page (in the comments)
/// <summary>
/// Returns a site relative HTTP path from a partial path starting out with a ~.
/// Same syntax that ASP.Net internally supports but this method can be used
/// outside of the Page framework.
///
/// Works like Control.ResolveUrl including support for ~ syntax
/// but returns an absolute URL.
/// </summary>
/// <param name="originalUrl">Any Url including those starting with ~</param>
/// <returns>relative url</returns>
public static string ResolveUrl(string originalUrl)
{
if (string.IsNullOrEmpty(originalUrl))
return originalUrl;
// *** Absolute path - just return
if (IsAbsolutePath(originalUrl))
return originalUrl;
// *** We don't start with the '~' -> we don't process the Url
if (!originalUrl.StartsWith("~"))
return originalUrl;
// *** Fix up path for ~ root app dir directory
// VirtualPathUtility blows up if there is a
// query string, so we have to account for this.
int queryStringStartIndex = originalUrl.IndexOf('?');
if (queryStringStartIndex != -1)
{
string queryString = originalUrl.Substring(queryStringStartIndex);
string baseUrl = originalUrl.Substring(0, queryStringStartIndex);
return string.Concat(
VirtualPathUtility.ToAbsolute(baseUrl),
queryString);
}
else
{
return VirtualPathUtility.ToAbsolute(originalUrl);
}
}
/// <summary>
/// This method returns a fully qualified absolute server Url which includes
/// the protocol, server, port in addition to the server relative Url.
///
/// Works like Control.ResolveUrl including support for ~ syntax
/// but returns an absolute URL.
/// </summary>
/// <param name="ServerUrl">Any Url, either App relative or fully qualified</param>
/// <param name="forceHttps">if true forces the url to use https</param>
/// <returns></returns>
public static string ResolveServerUrl(string serverUrl, bool forceHttps)
{
if (string.IsNullOrEmpty(serverUrl))
return serverUrl;
// *** Is it already an absolute Url?
if(IsAbsolutePath(serverUrl))
return serverUrl;
string newServerUrl = ResolveUrl(serverUrl);
Uri result = new Uri(HttpContext.Current.Request.Url, newServerUrl);
if (!forceHttps)
return result.ToString();
else
return ForceUriToHttps(result).ToString();
}
/// <summary>
/// This method returns a fully qualified absolute server Url which includes
/// the protocol, server, port in addition to the server relative Url.
///
/// It work like Page.ResolveUrl, but adds these to the beginning.
/// This method is useful for generating Urls for AJAX methods
/// </summary>
/// <param name="ServerUrl">Any Url, either App relative or fully qualified</param>
/// <returns></returns>
public static string ResolveServerUrl(string serverUrl)
{
return ResolveServerUrl(serverUrl, false);
}
/// <summary>
/// Forces the Uri to use https
/// </summary>
private static Uri ForceUriToHttps(Uri uri)
{
// ** Re-write Url using builder.
UriBuilder builder = new UriBuilder(uri);
builder.Scheme = Uri.UriSchemeHttps;
builder.Port = 443;
return builder.Uri;
}
private static bool IsAbsolutePath(string originalUrl)
{
// *** Absolute path - just return
int IndexOfSlashes = originalUrl.IndexOf("://");
int IndexOfQuestionMarks = originalUrl.IndexOf("?");
if (IndexOfSlashes > -1 &&
(IndexOfQuestionMarks < 0 ||
(IndexOfQuestionMarks > -1 && IndexOfQuestionMarks > IndexOfSlashes)
)
)
return true;
return false;
}
Related
What differences, if any are there between:
System.Web.HttpUtility.HtmlEncode
System.Web.HttpServerUtility.HtmlEncode
System.Net.WebUtility.HtmlEncode
Both HttpUtility.HtmlEncode and HttpServerUtility.HtmlEncode say:
To encode or decode values outside of a web application, use the WebUtility class.
Which implies that there is a difference, but doesn't come out say so directly or say what the difference is, if there is one.
If you dig though the source code you can follow easily enough.
System.Web.HttpUtility.HtmlEncode
/// <devdoc>
/// <para>
/// HTML encodes a string and returns the encoded string.
/// </para>
/// </devdoc>
public static String HtmlEncode(String s) {
return HttpEncoder.Current.HtmlEncode(s);
}
System.Web.HttpServerUtility.HtmlEncode
/// <devdoc>
/// <para>
/// HTML
/// encodes a given string and
/// returns the encoded string.
/// </para>
/// </devdoc>
public string HtmlEncode(string s) {
return HttpUtility.HtmlEncode(s);
}
System.Net.WebUtility.HtmlEncode
public static string HtmlEncode(string value) {
if (String.IsNullOrEmpty(value)) {
return value;
}
// Don't create string writer if we don't have nothing to encode
int index = IndexOfHtmlEncodingChars(value, 0);
if (index == -1) {
return value;
}
StringWriter writer = new StringWriter(CultureInfo.InvariantCulture);
HtmlEncode(value, writer);
return writer.ToString();
}
So System.Web.HttpServerUtility.HtmlEncode actually uses System.Web.HttpUtility.HtmlEncode. If you drill into HttpEncoder.Current.HtmlEncode(s); this has the following code:
protected internal virtual void HtmlDecode(string value, TextWriter output) {
WebUtility.HtmlDecode(value, output);
}
Tl;Dr
So they all, ultimately, use System.Net.WebUtility.HtmlEncode. I guess the System.Web version are only there for backwards compatibillity. Hence the advice of using the System.Net version.
Currently I do this
try
{
cloudFilesProvider.CreateObjectFromFile(inStrContainerName, inStrSrcFilePath, strDesFileName, 4096, FileMetaData);
}
catch (ItemNotFoundException ex1)
{
try
{
cloudFilesProvider.CreateContainer(inStrContainerName);
cloudFilesProvider.CreateObjectFromFile(inStrContainerName, inStrSrcFilePath, strDesFileName, 4096, FileMetaData);
}
catch(Exception ex2)
{
return false;
}
}
So essentially if the container does not exist then its 3 separate API calls.
Is there a more efficient way to do this?
You can simplify the code by reducing it to the following two lines.
cloudFilesProvider.CreateContainer(inStrContainerName);
cloudFilesProvider.CreateObjectFromFile(inStrContainerName, inStrSrcFilePath, strDesFileName, 4096, FileMetaData);
CreateContainer is safe to call for a container that already exists. It returns ContainerCreated if the container is created, or ContainerExists if the container was not created because it already exists.
PS: The return values (with information like the above) for the IObjectStorageProvider methods will be well documented for release 1.2.0.0.
Edit: To reduce the number of API calls your code makes, you could use a cache class like the following. The CreateIfNecessary method attempts to create the container only if it is not previously known to exist. The ClearCache method provides a manual method for continuing to use the cache even if you delete a container.
This code is currently untested.
public class ContainerManager
{
private readonly CloudFilesProvider _provider;
private readonly string _region;
private readonly bool _useInternalUrl;
private readonly CloudIdentity _identity;
private readonly HashSet<string> _containers = new HashSet<string>();
public ContainerManager(CloudFilesProvider provider, string region, bool useInternalUrl, CloudIdentity identity)
{
if (provider == null)
throw new ArgumentNullException("provider");
_provider = provider;
_region = region;
_useInternalUrl = useInternalUrl;
_identity = identity;
}
/// <summary>
/// Clears the cache of known containers.
/// </summary>
/// <remarks>
/// <alert class="warning">
/// If a container was deleted after this cache was in use, this method must be called or
/// <see cref="CreateIfNecessary(string)"/> could fail to create a container which does not
/// exist.
/// </alert>
/// </remarks>
public void ClearCache()
{
lock (_containers)
{
_containers.Clear();
}
}
/// <summary>
/// Ensures that a container exists in the Cloud Files store.
/// </summary>
/// <remarks>
/// <alert class="warning">
/// If a container was deleted after this cache was in use, and <see cref="ClearCache()"/>
/// has not been called, this method could fail to create a container which does not exist.
/// </alert>
/// </remarks>
/// <param name="container">The name of the container to create.</param>
/// <exception cref="ArgumentNullException">If <paramref name="container"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If <paramref name="container"/> is empty.</exception>
/// <returns><c>true</c> if the container was created; otherwise <c>false</c> if the container already existed.</returns>
public bool CreateIfNecessary(string container)
{
if (container == null)
throw new ArgumentNullException("container");
if (string.IsNullOrEmpty(container))
throw new ArgumentException("container cannot be empty");
// don't try to create the same container multiple times
if (_containers.Contains(container))
return false;
ObjectStore result = _provider.CreateContainer(container, _region, _useInternalUrl, _identity);
if (result == ObjectStore.ContainerCreated || result == ObjectStore.ContainerExists)
{
lock (_containers)
{
// add to _containers even if the result is ContainerExists, because that
// means it simply wasn't known to this cache.
_containers.Add(container);
}
}
// only return true if the container was actually created
return result == ObjectStore.ContainerCreated;
}
}
Using vanilla MVC I can revalidate my model with TryValidateModel. The TryValidateModel method doesn't seem to be applicable to WebAPI. How can I revalidate my model when using WebAPI?
I know it has been a while since this has been asked, but the problem is still valid. Thus i thought i should share my solution to this problem.
I decided to implement the TryValidateModel(object model) myself, based on the implementation in the System.Web.Mvc.Controller.cs
The problem is that the mvc's TryValidateModel internally used their own HttpContext and ModelState. If you go and compaire the two, they are very similar....
The be able to use our own HttpContext there exists a HttpContextWrapper that can be used for that.
And Since we have to clear our model state, it doesn't really matter that we use a different type of ModelState , as long as we get the desired result, thus i create a new ModelState object from the correct type...
I did add the error to the ModelState of the controller and not to the model state to the newly created ModelState , This seems to work just fine for me :)
Here is my code, that i just added to the controller...
do not forget to import the library...
using System.Web.ModelBinding;
protected internal bool TryValidateModel(object model)
{
return TryValidateModel(model, null /* prefix */);
}
protected internal bool TryValidateModel(object model, string prefix)
{
if (model == null)
{
throw new ArgumentNullException("model");
}
ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType());
var t = new ModelBindingExecutionContext(new HttpContextWrapper(HttpContext.Current), new System.Web.ModelBinding.ModelStateDictionary());
foreach (ModelValidationResult validationResult in ModelValidator.GetModelValidator(metadata, t).Validate(null))
{
ModelState.AddModelError(validationResult.MemberName, validationResult.Message);
}
return ModelState.IsValid;
}
I don't know when was it added but now there is Validate method on api controller.
ApiController.Validate Method (TEntity)
https://msdn.microsoft.com/en-us/library/dn573258%28v=vs.118%29.aspx
Based from rik-vanmechelen original answer, here is my version that relies on the services container exposed by Web API.
/// <summary>
/// Tries to validate the model.
/// </summary>
/// <param name="model">The model.</param>
/// <returns>Whether the model is valid or not.</returns>
protected internal bool TryValidateModel(object model)
{
if (model == null)
{
throw new ArgumentNullException("model");
}
var metadataProvider = Configuration.Services.GetService<System.Web.Http.Metadata.ModelMetadataProvider>();
var validatorProviders = Configuration.Services.GetServices<System.Web.Http.Validation.ModelValidatorProvider>();
var metadata = metadataProvider.GetMetadataForType(() => model, model.GetType());
ModelState.Clear();
var modelValidators = metadata.GetValidators(validatorProviders);
foreach (var validationResult in modelValidators.SelectMany(v => v.Validate(metadata, null)))
{
ModelState.AddModelError(validationResult.MemberName, validationResult.Message);
}
return ModelState.IsValid;
}
This uses the following simple extension methods to access the services :
/// <summary>
/// Services container extension methods.
/// </summary>
public static class ServicesContainerExtensions
{
/// <summary>
/// Gets the service.
/// </summary>
/// <typeparam name="TService">The type of the service.</typeparam>
/// <param name="services">The services.</param>
/// <returns>The service.</returns>
/// <exception cref="System.ArgumentNullException">services</exception>
public static TService GetService<TService>(this ServicesContainer services)
{
if (services == null)
{
throw new ArgumentNullException("services");
}
return (TService)((object)services.GetService(typeof(TService)));
}
/// <summary>
/// Gets the services.
/// </summary>
/// <typeparam name="TService">The type of the service.</typeparam>
/// <param name="services">The services.</param>
/// <returns>The services.</returns>
/// <exception cref="System.ArgumentNullException">services</exception>
public static IEnumerable<TService> GetServices<TService>(this ServicesContainer services)
{
if (services == null)
{
throw new ArgumentNullException("services");
}
return services.GetServices(typeof(TService)).Cast<TService>();
}
}
The advantage of using this method is that it reuses the MetadataProvider and ValidatorProvider(s) you have configured for your Web API application while the previous answer is retrieving the one configured in ASP.NET MVC.
ASP.NET MVC and WebAPI run through different pipelines.
Turns out TryValidateModel is not supported in WebAPI. There's a feature request over on CodePlex.
I have an MVC3 application on .net4 that its session working in the dev Environment, but not in the production.
In the production I logged the sessionID and the it is the same in the moment I Set and Get from the session.
When I try to get the session I am getting Null Exception.
This is how I access the session:
public static class HandlersHttpStorage
{
public static string TestSession
{
get
{
return HttpContext.Current.Session["time"];//This is null
}
set
{
HttpContext.Current.Session.Add("time", value);//DateTime.Now.ToString()
}
}
}
What's makes me worried is that the behavior in the production is different than the development, even though the web.config is the same.
Solution 1:
Link: HttpContext.Current.Session is null when routing requests
Got it. Quite stupid, actually. It worked after I removed & added the SessionStateModule like so:
<configuration>
...
<system.webServer>
...
<modules>
<remove name="Session" />
<add name="Session" type="System.Web.SessionState.SessionStateModule"/>
...
</modules>
</system.webServer>
</configuration>
Simply adding it won't work since "Session" should have already been defined in the machine.config.
Now, I wonder if that is the usual thing to do. It surely doesn't seem so since it seems so crude...
Solution 2:
Link: HttpContext.Current.Session null item
sessionKey may be changing, you probably only need to do:
HttpContext.Current.Session["CurrentUser"]
Or the session may be expiring, check the timeout:
http://msdn.microsoft.com/en-us/library/h6bb9cz9(VS.71).aspx
Or you may be setting the session value from somewhere else, normally i control access to Session/Context object through one property
static readonly string SESSION_CurrentUser = "CurrentUser";
public static SiteUser Create() {
SiteUser.Current = new SiteUser();
return SiteUser.Current;
}
public static SiteUser Current {
get {
if (HttpContext.Current.Session == null || HttpContext.Current.Session[SESSION_CurrentUser] == null) {
throw new SiteUserAutorizationExeption();
}
return HttpContext.Current.Session[SESSION_CurrentUser] as SiteUser;
}
set {
if (!HttpContext.Current.Session == null) {
HttpContext.Current.Session[SESSION_CurrentUser] = value;
}
}
}
Another possible cause/solution is that IE doesn't save cookies if the domain name has an underscore (because strictly speaking domain names can't have underscores, so you'll probably only encounter this in development), e.g. http://my_dev_server/DoesntWork. Chrome or Firefox should work in this scenario, and if you change the domain name you're using to not have an underscore problem solved.
Ref:
http://blog.smartbear.com/software-quality/internet-explorer-eats-cookies-with-underscores-in-the-hostname/
http://social.msdn.microsoft.com/Forums/ie/en-US/8e876e9e-b223-4f84-a5d1-1eda2c2bbdf4/ie7-cookie-issue-when-domain-name-has-underscore-character-in-it?forum=iewebdevelopment
For me, I found that HttpContext.Current was null, so I created it:
System.Web.HttpContext c = System.Web.HttpContext.Current;
And I passed that into my function that was in my other class, like this:
string myString = "Something to save";
SessionExtensions.SetDataToSession<string>(c, "MyKey1", myString);
I had actually wanted my function to be a real extension method off of Session like the one below, but what I found was this HttpSessionStateBase session was null, it would give the NullReferenceException when I tried to add anything to Session using it. So this:
public static class SessionExtensions
{
/// <summary>
/// Get value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="session"></param>
/// <param name="key"></param>
/// <returns></returns>
public static T GetDataFromSession<T>(this HttpSessionStateBase session, string key)
{
return (T)session[key];
}
/// <summary>
/// Set value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="session"></param>
/// <param name="key"></param>
/// <param name="value"></param>
public static void SetDataToSession<T>(this HttpSessionStateBase session, string key, object value)
{
session[key] = value;
}
}
That Microsoft had here: https://code.msdn.microsoft.com/How-to-create-and-access-447ada98 became this, instead:
public static class SessionExtensions
{
/// <summary>
/// Get value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="session"></param>
/// <param name="key"></param>
/// <returns></returns>
public static T GetDataFromSession<T>(HttpContext context, string key)
{
if (context != null && context.Session != null)
{
context.Session.Abandon();
}
return (T)context.Session[key];
}
/// <summary>
/// Set value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="session"></param>
/// <param name="key"></param>
/// <param name="value"></param>
public static void SetDataToSession<T>(HttpContext context, string key, object value)
{
context.Session[key] = value;
}
}
And I was able to retrieve my data like this:
System.Web.HttpContext c = System.Web.HttpContext.Current;
string myString = SessionExtensions.GetDataFromSession<string>(c, "MyKey1");
And, of course, since HttpContext.Current and Session now exists, I was able to even simplify that to be:
string myString = Session["MyKey1"].ToString();
If this had been object, you would put the object's type in place of <string> in the SetDataToSession()
function:
List<string> myStringList = new List<string>();
myStringList.Add("Something to save");
SessionExtensions.SetDataToSession<List<string>>(c, "MyKey1", myStringList);
And to retrieve it:
System.Web.HttpContext c = System.Web.HttpContext.Current;
List<string> myStringList = SessionExtensions.GetDataFromSession<List<string>>(c, "MyKey1");
or simply:
List<string> myStringList = (List<string>)Session["MyKey1"];
i have an object which contains Max value and Min value,, so i want inside all the edit and create views to display a client side validation message incase the user insert the Min value greater then the Min value.
BR
You will probably want both client-side and server-side validation. It might be good to implement your own Validation. I did a similar thing in which I wanted to make sure that one field was NOT the same value as another field. I didn't start from scratch though. I used some code from Simon J Ince of Microsoft. He has it here on his blog. Basically he has a foundation of Conditional Validation (where you validate based on the value of another field). I inherited from his ConditionalAttributeBase and implemented the IClientValidatable interface (this is how you send to the browser the dependent field the java script will check with.)
/// <summary>
/// A validator for ensuring that the value of this field does NOT equal the value of another field.
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
public class NotEqual:ConditionalAttributeBase, IClientValidatable
{
public string DependentProperty { get; set; }
/// <summary>
/// Returns client validation rules for NotEqual
/// </summary>
/// <param name="metadata">The model metadata.</param>
/// <param name="context">The controller context.</param>
/// <returns>
/// The client validation rules for NotEqual.
/// </returns>
IEnumerable<ModelClientValidationRule> IClientValidatable.GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
ValidationType = "notequal",
};
string depProp = BuildDependentPropertyId(metadata, context as ViewContext);
rule.ValidationParameters.Add("dependentproperty", depProp);
yield return rule;
}
/// <summary>
/// Builds the dependent property id.
/// </summary>
/// <param name="metadata">The metadata.</param>
/// <param name="viewContext">The view context.</param>
/// <returns></returns>
protected string BuildDependentPropertyId(ModelMetadata metadata, ViewContext viewContext)
{
return QualifyFieldId(metadata, DependentProperty, viewContext);
}
/// <summary>
/// Validates that the value does not equal the value of the dependent value if the dependent value is not null
/// </summary>
/// <param name="value">The value to validate.</param>
/// <param name="validationContext">The context information about the validation operation.</param>
/// <returns>
/// An instance of the <see cref="T:System.ComponentModel.DataAnnotations.ValidationResult"/> class.
/// </returns>
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
// check if the current value matches the target value
if (value != null && GetDependentFieldValue(DependentProperty, validationContext).ToString() == value.ToString())
{
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
return ValidationResult.Success;
}
/// <summary>
/// Initializes a new instance of the <see cref="NotEqual"/> class.
/// </summary>
/// <param name="dependentProperty">The dependent property.</param>
public NotEqual(string dependentProperty)
{
DependentProperty = dependentProperty;
}
}$
Next I tweaked the javascript:
(function ($) {
$.validator.addMethod('notequal',
function (value, element, parameters) {
var id = '#' + parameters['dependentproperty'];
var depControl = $(id);
var control = $(element);
if (control.val() === depControl.val())
return "";
return true;
}
);
$.validator.unobtrusive.adapters.add(
'notequal',
['dependentproperty'],
function (options) {
options.rules['notequal'] = {
dependentproperty: options.params['dependentproperty']
};
options.messages['notequal'] = options.message;
}
);
$.validator.addMethod('notequaltwo',
function (value, element, parameters) {
var id = '#' + parameters['dependentproperty'];
var depControl = $(id);
var control = $(element);
if (control.val() === depControl.val())
return "";
return true;
}
);
$.validator.unobtrusive.adapters.add(
'notequaltwo',
['dependentproperty'],
function (options) {
options.rules['notequaltwo'] = {
dependentproperty: options.params['dependentproperty']
};
options.messages['notequaltwo'] = options.message;
}
);
})(jQuery);$
Hopefully you can see how you can adapt my code to do what you want it do, basically you would have to convert the types (if the types don't convert, don't do anything and other validators that you have should pick up on it.) and then do a compare.