c# function, validate url within mvc app - c#

I'm trying to build a function within my mvc app that will validate the user's url input. in my code below, i get the "not all code paths return a value." I need help figuring out why it doesn't like when i return result. thanks!
public static long InsertUrl(string inputUrl)
{
long result = 0;
if (!string.IsNullOrEmpty(inputUrl))
{
using (ShortUrlEntities db = new ShortUrlEntities())
{
if (inputUrl.IndexOf(#"://test/") == -1)
{
inputUrl = "http://test/" + inputUrl;
}
Regex RgxUrl = new Regex("(([a-zA-Z][0-9a-zA-Z+\\-\\.]*:)?/{0,2}[0-9a-zA-Z;/?:#&=+$\\.\\-_!~*'()%]+)?(#[0-9a-zA-Z;/?:#&=+$\\.\\-_!~*'()%]+)?");
if (RgxUrl.IsMatch(inputUrl))
{
ShortURL su = new ShortURL();
su.url = inputUrl;
db.AddToShortURLSet(su);
db.SaveChanges();
result = su.id;
}
return result;
}
}
}
}
}

You have an If
if (!string.IsNullOrEmpty(inputUrl))
and your return is inside that if. In the event that the inputUrl is null or empty, you are not returning anything.
Move your return Result; to outside the if.

The problem is that if this:
if (!string.IsNullOrEmpty(inputUrl))
fails then no result will ever be returned. This is needed for all function that return a value not just in MVC.

Related

C# - Using File.Exists, when file DOESN'T exist does not run the last else statement

Super new to C#. I'm having an input get split and then find an ID from the pointsTarget var.
When the file DOES exist, it seems that the line
else if (File.Exists(filePath+userId+txt))
returns true;
because it runs just fine and sets the argument "addPointsCompleted" to TRUE. It works just how I would expect. But when the file does NOT exist, I want it to return false and run the last else statement:
CPH.SetArgument("missing", "True");
and set "missing" to TRUE.
I feel like there is something wrong with the way I put in the if/else if/else statement because I get an error :
"System.IO.FileNotFoundException: Could not find file 'E:\Users\Troy\Documents\Stuff\PointNames\Test.txt'.
using System;
using System.IO;
public class CPHInline
{
public bool Execute()
{
string rawInput = args["rawInput"].ToString();
string[] split= rawInput.Split('+');
var pointsTarget = split[0].ToString();
var addPoints = split[1].ToString();
CPH.LogInfo($"pointsTarget is {pointsTarget}");
CPH.LogInfo($"addPoints is {addPoints}");
var user = args["user"].ToString();
CPH.SetArgument("pointsTarget", pointsTarget);
string userPath = #"E:/Users/Troy/Documents/Stuff/PointNames/";
string filePath = #"E:/Users/Troy/Documents/Stuff/PointIDs/";
string txt = ".txt";
var userId = File.ReadAllText(userPath+pointsTarget+txt);
CPH.LogInfo($"userId is {userId}");
if (user == pointsTarget)
{
CPH.SetArgument("corrupt", "True");
}
else if (File.Exists(filePath+userId+txt))
{
//DO THIS
string fileName = filePath+userId+txt;
string points = File.ReadAllText(fileName);
int x = Convert.ToInt32(points);
int y = Convert.ToInt32(addPoints);
int sum = x + y;
String newPoints;
newPoints = sum.ToString();
File.WriteAllText(fileName, newPoints);
CPH.SetArgument("newPoints", newPoints);
CPH.SetArgument("addPointsCompleted", "True");
}
else
{
//do this
CPH.SetArgument("missing", "True");
}
return true;
}
}
I tried looking around, but all the issues are from people where the file DOES exist and they can't find it. My problem is kind of the opposite.
I feel like there is something wrong with the way I put in the if/else if/else statement because I get an error "System.IO.FileNotFoundException: Could not find file 'E:\Users\Troy\Documents\Stuff\PointNames\Test.txt'.
This is a good opportunity for you to start familiarizing yourself with using a debugger to step through the code and observe its behavior. Because the problem has nothing to do with your if structure. It's happening before your if block. Right here:
var userId = File.ReadAllText(userPath+pointsTarget+txt);
Look at the error message. It's trying to read a file in the "PointNames" folder. Which is in your userPath variable:
string userPath = #"E:/Users/Troy/Documents/Stuff/PointNames/";
Which is only ever used in that one line of code that tries to read a file. And File.ReadAllText will throw a FileNotFoundException if the file is not found.
It seems you're already aware of how to check if a file exists. So why not apply that here? For example:
var userId = string.Empty;
if (File.Exists(userPath+pointsTarget+txt))
{
userId = File.ReadAllText(userPath+pointsTarget+txt);
}
else
{
// handle the error in some way
}

Passing empty IEnumerable<> to constructor

Based on the current content in the database two things happen.
If the table buildingDefine is not empty, pass this table to the constructor.
else pass and empty table of buildingDefine to the constructor.
Here is my check for towards the database:
//Is there content in buildingDefineTable?
if (!_bDefine.Any())
{
int currentBuildingId = ((BuildingTable)((ListView)sender).SelectedItem).Id;
var currentBool = from bla in _building
where bla.Id == currentBuildingId
select bla.BuildingBool;
//Is the buildingBool false?
if (!currentBool.First())
{
var currentBuildingDefine = from BuildingDefineTable in _bDefine
where BuildingDefineTable.buildingId == ((BuildingTable)((ListView)sender).SelectedItem).Id
select BuildingDefineTable;
await Navigation.PushAsync(new DefineBuilding(currentBuildingDefine));
}
else
{
//Do something here.
}
}
//No content in buildingDefineTable
else
{
await Navigation.PushAsync(new DefineBuilding(new IEnumerable<_bDefine> bDefineTable ));
}
The if sentence works fine, however I am not able to pass an empty list of the table, whenever the database does not contain any information in the table.
This is my constructor:
public DefineBuilding(IEnumerable<BuildingDefineTable> bDefineTable)
{
if (bDefineTable == null) throw new ArgumentNullException();
BindingContext = bDefineTable;
//More code here
}
Any ideas on how to solve this?
Use Enumerable.Empty
var x = new DefineBuilding(Enumerable.Empty<BuildingDefineTable>());

replacing a variable text with other text in c#

I am using c# and sitecore to basically use tokens in certain places ( see: how to create a custom token in sitecore ). I think I have a solution, but am not sure as to why it is not working, even though I am getting no errors.
Item tokenItem = Sitecore.Context.Database.Items["/sitecore/content/Site Content/Tokens"];
if (tokenItem.HasChildren)
{
var sValue = args.FieldValue.ToString();
foreach (Item child in tokenItem.Children)
{
if (child.Template.Name == "Token")
{
string home = child.Fields["Title"].Value;
string hContent = child.Fields["Content"].Value;
if (sValue.Contains(home))
{
home.Replace(home, hContent);
}
}
}
}
home and hContent pull up the correct values of each container, but when the page loads, it still has the "home" value inputted (the ie: ##sales) in the content area instead of the new value, which is stored in hContent. The sValue contains everything (tables, divs, text) and I was trying to single out a value that equals to "home" and replace the "home" value with hContent. What am I missing?
If your code is implemented as a processor for the RenderField pipeline, you need to put the result of your work back into args. Try something like this:
Item tokenItem = Sitecore.Context.Database.Items["/sitecore/content/Site Content/Tokens"];
if (tokenItem.HasChildren)
{
var sValue = args.Result.FirstPart;
foreach (Item child in tokenItem.Children){
if (child.Template.Name == "Token") {
string home = child.Fields["Title"].Value;
string hContent = child.Fields["Content"].Value;
if (sValue.Contains(home)) {
sValue = sValue.Replace(home, hContent);
}
}
}
args.Result.FirstPart = sValue;
}
Note that you need to be sure to patch this processor into the pipeline after the GetFieldValue processor. That processor is responsible for pulling the field value into args.Result.FirstPart.
You code isn't really doing anything. You seem to be replacing the tokens on the token item field itself (child.Fields["Title"] and child.Fields["Content"]), not on the output content stream.
Try the following, you need to set the args to the replaced value, replacing both the FirstPart and LastPart properties: Replace Tokens in Rich Text Fields Using the Sitecore ASP.NET CMS (link to the code in the "untested prototype" link).
I would refactor your code to make it easier:
public void Process(RenderFieldArgs args)
{
args.Result.FirstPart = this.Replace(args.Result.FirstPart);
args.Result.LastPart = this.Replace(args.Result.LastPart);
}
protected string Replace(string input)
{
Item tokenItem = Sitecore.Context.Database.Items["/sitecore/content/Site Content/Tokens"];
if (tokenItem.HasChildren)
{
foreach (Item child in tokenItem.Children)
{
if (child.Template.Name == "Token")
{
string home = child.Fields["Title"].Value;
string hContent = child.Fields["Content"].Value;
if (input.Contains(home))
{
return input.Replace(home, hContent);
}
}
}
}
return input;
}
This is still not optimal, but gets you closer.
Well, Do you know what happens when you performs home.Replace(home, hContent);, it will create a new instance by replacing the content of the come with what is in hContent so what you need to do is, assign this instance to a new variable or to home itself. hence the snippet will be like the following:
if (sValue.Contains(home))
{
home = home.Replace(home, hContent);
}
Have you tried:
home = home.Replace(home,hContent);

FluentValidation passing parameter

I've found FluentValidation only couple of hours ago and I want to rewrite all my validation logic so it will use only FV.
The issue that I have ATM is that I would like to use data coming from input as a parameter for DomainExists() method. Is it possible or do I have to figure out a way around FV to achieve that?
public QuoteValidator()
{
// hardcoded because don't know how to pass input string to RuleFor
var inputeddomain = "http://google.com";
RuleFor(r => r.Domain).NotEqual(DomainExists(inputeddomain));
}
// checks if inputeddomain is in repository (SQL DB)
private string DomainExists(string inputeddomain)
{
var context = new QuoteDBContext().Quotes;
var output = (from v in context
where v.Domain == inputeddomain
select v.Domain).FirstOrDefault();
if (output != null) { return output; } else { return "Not found"; }
}
Thanks to #bpruitt-goddard hint I got that to work. Here's a solution to my problem (hope it will help somebody).
public QuoteValidator()
{
RuleFor(r => r.Domain).Must(DomainExists).WithMessage("{PropertyValue} exists in system!");
}
private bool DomainExists(string propertyname)
{
var context = new QuoteDBContext().Quotes;
var output = (from v in context
where v.Domain == propertyname
select v.Domain).FirstOrDefault();
if (output != null) { return false; } else { return true; }
}
You can use FluentValidation's Must method to pass in extra data from the input object.
RuleFor(r => r.Domain)
.Must((obj, domain) => DomainExists(obj.InputDomain))
.WithErrorCode("MustExist")
.WithMessage("InputDomain must exist");
Although this will work, it is not recommended to check for database existence in the validation layer as this is verification versus validation. Instead, this kind of check should be done in the business layer.

Not all paths return a value. - Optional return?

I am getting the error "Not all paths return a value", and I totally understand why.
As you can see I want to redirect the person isn't logged in, and obviously there is no return view.
I'm sure I'm going about this incorrectly. How should I be trying to do this?
public ActionResult Confirmation (Order Order) {
if (Session["CompanyID"] == null)
{
string url = Request.Url.Host;
if (Request.Url.Port != null)
{
url = url + Request.Url.Port;
}
url = url + "/signin.asp";
Response.Redirect(url);
}
else
{
int userID = (int)Session["CompanyID"];
Corp_User User = Repository.CorpUserDetails(userID);
return View(new OrderLocation { Order = Order, Location = WhygoRepository.RoomDetails(Order.roomId).First(), Corp_User = User });
}
}
Please note that I need to redirect to a classic ASP page, not an MVC action..
You must return a ActionResult. Use "RedirectToAction".
public ActionResult Confirmation(Order Order)
{
if (Session["CompanyID"] == null)
{
string url = Request.Url.Host;
if (Request.Url.Port != null)
{
url = url + Request.Url.Port;
}
url = url + "/signin.asp";
return RedirectToAction(<YOUR ACTION>);
}
else
{
int userID = (int)Session["CompanyID"];
Corp_User User = Repository.CorpUserDetails(userID);
return View(new OrderLocation { Order = Order, Location = WhygoRepository.RoomDetails(Order.roomId).First(), Corp_User = User });
}
}
You could return a RedirectResult - http://msdn.microsoft.com/en-us/library/system.web.mvc.redirectresult.aspx
Well, this is a good question actually. See dknaack's answer for a solution in your particular case however in other circumstances we might not be so lucky.
Technically this situation is very logical. Redirect just opens up a new request and either lets the current request handle itself nicely or forcefully close itself. In all cases the current method needs a return value. If Redirect lets the current process handle itself nicely meaning you should have a return value that makes sense.
I think one solution would be to throw a specific exception after the redirect. Something like:
public string GetCurrentUserName()
{
if (!authenticated)
{
Response.Redirect(LoginScreen);
throw new UnresolvedMethodException();
}
else
{
return UserName;
}
}
Returning NULL is an option i wouldnt put my money on since NULL might also mean that there is no UserName Set (in the above case, a user might login using his email making the username optional).
Just put return null; under Response.Redirect(url); It will never actually reach that position, but it will get rid of the compiler error.
You could return null and check for that.
edit: I was way to quick, ignore me :P

Categories

Resources