I have a situation where I need to restrict a user to enter a Url which already exits in DB.
Here is the function that I am using to validate:
public bool IsContentUrlExists(string url)
{
url = url.Trim().TrimEnd(new[]{'/'});
return Context.Contents.Any(content => content.Url == url);
}
With this method I can validate for a Url say "/testurl/" that matches a url "/testurl" in DB.
But otherway it will not work when I go to compare "/testurl" string with "/testurl/" in DB.
I need to remove the trailing slash in both case but TrimEnd(new[]{'/'}) will not work on a column in EF query. So the following method will fail
public bool IsContentUrlExists(string url)
{
url = url.Trim().TrimEnd(new[]{'/'});
return Context.Contents.Any(content => content.Url.Trim().TrimEnd(new[]{'/'}) == url);
}
Can anyone help me with an alternative solution?
N.B: We don't have any standard for URL in our existing DB
Using your code plus mine
public bool IsContentUrlExists(string url)
{
url = url.Trim().TrimEnd(new[]{'/'});
return Context.Contents.Any(content => content.Url == url || content.Url == url + "/");
}
Untested but something like the above shoudl work, shouldn't it?
Wing
As an alternate you can try:
url = url.Trim().TrimEnd(new[] { '/' });
var lstUrls = new List<string> { url, url + "/" };
return Context.Contents.Any(content => lstUrls.Contains(content.Url));
It compares a list of two strings: one ending with slash and the other without.
If there will be a match for any of these two strings in database then it means the URL exists!
Related
I wrote this code in a C# ASP.NET Core Web API project:
[HttpGet]
[Route("GetShortURL/{_url}/{tokenPass}")]
[ApiExplorerSettings(GroupName = "ShortURL")]
public ActionResult<ServiceResult<string>> GetShortURL(string _url, string tokenPass)
When I enter this parameter as _url, I get an error:
Error: Not Found
https://github.com/VahidN/DNTPersianUtils.Core
http://...//GetShortURL/https%3A%2F%2Fgithub.com%2FVahidN%2FDNTPersianUtils.Core/TokenPass
How can I call this API with the first Web URL parameter?
when i change the [Route("GetShortURL/{_url}/{tokenPass}")] to [Route("GetShortURL")] the problem was solved but i want to send query by / not by ?
for example, i want to call API like this :
1- http://..../GetShortURL/_UrlParam/_TokenPassParam
not like below :
2- http://..../GetShortURL?_url=_urlParam&tokenPass=_TokenPassParam
the second way works fine but I want first way to work correctly when i pass an URL like this
https%3A%2F%2Fgithub.com%2FVahidN%2FDNTPersianUtils.Core
can anyone help me?
First approach:
Pass the params you want as query string and then change the method like below:
[HttpGet("GetShortURL")]
[ApiExplorerSettings(GroupName = "ShortURL")]
public ActionResult<ServiceResult<string>> GetShortURL(string _url, string tokenPass)
Then For extracting the different parts of the url (protocol, domain name, path and query string), use the code below (path is an array separated by slash):
try
{
var decodedUrl = System.Web.HttpUtility.UrlDecode(_url);
Uri uri = new Uri(decodedUrl);
var scheme = uri.Scheme;
var host = uri.Host;
var absolutePathSeperatedBySlash = uri.AbsolutePath.Split('/').Skip(1).ToList();
var query = uri.Query;
// rest of the code ...
}
catch (Exception ex)
{
//...
}
Second approach:
If you want it to be sent as a url parameter, first you have to encode the value of _url with encodeURIComponent() in javascript, to make sure that some special characters like , / ? : # & = + $ # are changed.
Then:
[HttpGet("GetShortURL/{_url}/{tokenPass}")]
[ApiExplorerSettings(GroupName = "ShortURL")]
public ActionResult<ServiceResult<string>> GetShortURL(string _url, string tokenPass)
The rest is just like the method body of the first approach.
With the following url
http://...//GetShortURL/https%3A%2F%2Fgithub.com%2FVahidN%2FDNTPersianUtils.Core/TokenPass
The value of _url will be:
If you want to convert it to a correct url,you needs to replace %2F with / in GetShortURL:
var url = _url.Replace("%2F","/");
just make parameters to be optional
[HttpGet("GetShortURL/{_url?}/{tokenPass?}")]
public ActionResult<ServiceResult<string>> GetShortURL(string _url, string tokenPass)
in this case you can call the action without any parameters, with one parameter or with two parameters
I have developed a SharePoint add-in (SharePoint Online) and it is hosted in Azure. The add-in is an ASP.NET MVC application.
Here's the situation:
/Home/Index: The user starts on the landing page of the application and goes to the section Actions.
Actions/Index: On this page, the user has to select a few parameters and select an action to edit
Actions/Edit/123: The edit page opens, a form is shown with all controls filled in with the information about the action.
POST: After changing some fields, or none, the user clicks the Save button.
I didn't show it in the list but all the URLs have the SPHostUrl, SPAppWebUrl, SPLanguage, SPClientTag & SPProductNumber parameters.
This all works fine, except when the user doesn't interact with the application/page for a number of minutes and then presses the Save button. When the button is pressed, the application fails to pass the SharePointContextFilter attribute. The SharePointContext doesn't "exist" anymore. Following line returns null:
SharePointContext spContext = LoadSharePointContext(httpContext);
Normally, if it doesn't exist or isn't valid, the code will try and create it based based on the request. In the CreateSharePointContext method, the contextTokenString is always null:
string contextTokenString = TokenHelper.GetContextTokenFromRequest(httpRequest);
This is the code of the method:
public static string GetContextTokenFromRequest(HttpRequestBase request)
{
string[] paramNames = { "AppContext", "AppContextToken", "AccessToken", "SPAppToken" };
foreach (string paramName in paramNames)
{
if (!string.IsNullOrEmpty(request.Form[paramName]))
{
return request.Form[paramName];
}
if (!string.IsNullOrEmpty(request.QueryString[paramName]))
{
return request.QueryString[paramName];
}
}
return null;
}
So, if this fails, the creation and saving of the context fails and the app returns the default error page.
This is the jQuery code that makes the call to the controller:
var request = $.ajax({
url: '#Url.Action("Edit", "Actions")' + window.buildSpAppParameters(),
data: $("#updateForm").serialize(),
cache: false,
type: "POST"
});
Here's the code of the buildSpAppParameters function:
function buildSpAppParameters() {
var spHostUrl = getQueryStringParameter("SPHostUrl");
var appWebUrl = getQueryStringParameter("SPAppWebUrl");
var spLanguage = getQueryStringParameter("SPLanguage");
var spClientTag = getQueryStringParameter("SPClientTag");
var spProductNr = getQueryStringParameter("SPProductNumber");
return "?SPHostUrl=" + spHostUrl +
"&SPAppWebUrl=" + appWebUrl +
"&SPLanguage=" + spLanguage +
"&SPClientTag=" + spClientTag +
"&SPProductNumber=" + spProductNr;
}
Why does this initially work, but if the user waits a period of time, the code is unable to get/create the context again? Is there something I am missing and how can solve this?
Note: I am aware of following question: Sharepoint 2013 MVC 5 provider-hosted app. Fails to authenticate on HttpPost using [SharePointContextFilter] and while there is useful information to read, it didn't help me further.
This all works fine, except when the user doesn't interact with the application/page for a number of minutes
The session is expired and the SharePointContext is lost. So we need to regenerate the context.
According to the GetContextTokenFromRequest method, the context token should be passed in query string or forms. But from the buildSpAppParameters method, we can't found the context token is passed from the query string. The query string parameter should be named AppContext or AppContextToken or AccessToken or SPAppToken.
To solve this issue, you could check whether your current URL in your brower contains a query parameter named AppContext or AppContextToken or AccessToken or SPAppToken. If yes, you could read the value this parameter out from URL and pass it server in your buildSpAppParameters method. For example, if your URL contains a query parameter named AppContextToken, you could modify your code as following.
function buildSpAppParameters() {
var spHostUrl = getQueryStringParameter("SPHostUrl");
var appWebUrl = getQueryStringParameter("SPAppWebUrl");
var spLanguage = getQueryStringParameter("SPLanguage");
var spClientTag = getQueryStringParameter("SPClientTag");
var spProductNr = getQueryStringParameter("SPProductNumber");
var appContextToken = getQueryStringParameter("AppContextToken");
return "?SPHostUrl=" + spHostUrl +
"&SPAppWebUrl=" + appWebUrl +
"&SPLanguage=" + spLanguage +
"&SPClientTag=" + spClientTag +
"&SPProductNumber=" + spProductNr +
"&AppContextToken=" + appContextToken;
}
If your URL doesn't contain such query parameters, you need to modify your code to store the context token in cookie when the context token was got at the first time.
string contextTokenString = TokenHelper.GetContextTokenFromRequest(httpRequest);
if (!string.IsNullOrEmpty(contextTokenString))
{
HttpCookie cookie = new HttpCookie("AppContextToken", contextTokenString);
cookie.HttpOnly = true;
Response.Cookies.Add(cookie);
}
After that, the context token can be got from the cookie if the token haven't been passed through query string.
public static string GetContextTokenFromRequest(HttpRequestBase request)
{
string[] paramNames = { "AppContext", "AppContextToken", "AccessToken", "SPAppToken" };
foreach (string paramName in paramNames)
{
if (!string.IsNullOrEmpty(request.Form[paramName]))
{
return request.Form[paramName];
}
if (!string.IsNullOrEmpty(request.QueryString[paramName]))
{
return request.QueryString[paramName];
}
}
if (request.Cookies["AppContextToken"] != null)
{
return request.Cookies["AppContextToken"].Value;
}
return null;
}
I have this method.
public ActionResult SetTempDataToChangeVendor(int vendorId, string url)
{
TempData["ChangeVendor"] = vendorId;
if (url == null) return Redirect("/");
var slug = _urlRecordRepository.Table.FirstOrDefault(s => s.Slug == url);
if (slug == null) RedirectToAction("PageNotFound", "Common");
return Redirect("/" + url);
}
It works just fine when it redirects to /. But when a url i supplied the TempData is empty, and I can't understand why.
TempData is a bucket where you can dump data that is only needed for the following request. That is, anything you put into TempData is discarded after the next request completes.
I am wanting to redirect a page to a secure connection for an ASPX file.
Clients are asked to copy and paste a URL that looks like this foo.com.au into the browser.
I have this code below working on the code behind file but am wondering when it is deployed to production if this will update the URL to have www after the https://www as the URL provided to clients does not have www in it?
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
if (!Request.IsLocal && !Request.IsSecureConnection)
{
string redirectUrl = Request.Url.ToString().Replace("http:", "https:");
Response.Redirect(redirectUrl);
}
}
Rather than using Request.Url, use Request.Url.AbsoluteUri. In addition, you should not assume that the URL will be entered in lowercase. I would revise the code to be:
if (!Request.IsLocal && !Request.IsSecureConnection)
{
if (Request.Url.Scheme.Equals(Uri.UriSchemeHttp, StringComparison.InvariantCultureIgnoreCase))
{
string sNonSchemeUrl = Request.Url.AbsoluteUri.Substring(Uri.UriSchemeHttp.Length);
// Ensure www. is prepended if it is missing
if (!sNonSchemeUrl.StartsWith("www", StringComparison.InvariantCultureIgnoreCase)) {
sNonSchemeUrl = "www." + sNonSchemeUrl;
}
string redirectUrl = Uri.UriSchemeHttps + sNonSchemeUrl;
Response.Redirect(redirectUrl);
}
}
If you do this, all it will change is the schema. So, if the absoluteUri is
http://foo.com.au
it will be changed to
https://foo.com.au
One last note: when we have done this, we have never tried it in OnPreInit, we always perform this logic in Page_Load. I am not sure what, if any, ramifications there will be for redirecting at that portion of the page lifecycle, but if you run into issues, you could move it into Page_Load.
This was my final implementation to account for a request comes through for https://foo and not https://www.foo
if (!Request.IsLocal &&
!Request.Url.AbsoluteUri.StartsWith("https://www.", StringComparison.OrdinalIgnoreCase))
{
string translatedUrl;
string nonSchemeUrl = Request.Url.AbsoluteUri;
string stringToReplace = (Request.Url.Scheme == Uri.UriSchemeHttp ? Uri.UriSchemeHttp + "://" : Uri.UriSchemeHttps + "://");
nonSchemeUrl = nonSchemeUrl.Replace(stringToReplace, string.Empty);
if (!nonSchemeUrl.StartsWith("www", StringComparison.InvariantCultureIgnoreCase))nonSchemeUrl = "www." + nonSchemeUrl;
translatedUrl = Uri.UriSchemeHttps + "://" + nonSchemeUrl;
Response.Redirect(nonSchemeUrl);
}
I can get my browser url using : string url = HttpContext.Current.Request.Url.AbsoluteUri;
But say if I have a url as below :
http://www.test.com/MyDirectory/AnotherDir/testpage.aspx
How would I get the "MyDirectory" part of it, is there a utility in .NET to get this or do I need string manipulation ?
If I do string manipulation and say anything after first instance of "/" then wouldnt it return the slash after http:? It would work if my url was www.test.com/MyDirectory/AnotherDir/testpage.aspx
Can someone please help
Instantiate a Uri instance from your url:
Uri myUri = new Uri("http://www.test.com/MyDirectory/AnotherDir/testpage.aspx");
You can then get the path segments into a string array using:
string[] segments = myUri.Segments
Your first "MyDirectory" folder will be at:
string myFolderName = segments[0];
You can get this by PathAndQuery property of Url
var path = HttpContext.Current.Request.Url.PathAndQuery;
it will return /MyDirectory/AnotherDir/testpage.aspx
Uri uriAddr = new Uri("http://www.test.com/MyDirectory/AnotherDir/testpage.aspx");
var firstSegment= uriAddress.Segments.Where(seg => seg != "/").First();