How to use if else in this action? - c#

How do you write an if/else statement for this method if there is no result?
public ActionResult Search(string q)
{
Helpers Helpers = new Helpers();
var restaurants = Helpers.getRestaurant(q);
return View("_RestaurantSearchResults", restaurants);
}
Helpers class contains:
public class Helpers
{
FoodReviewContext _db = new FoodReviewContext();
public static IQueryable<Restaurant> getRestaurant(string q)
{
var restaurents = _db.Restaurants
.Where(r => r.Name.StartsWith(q) || String.IsNullOrEmpty(q))
.Take(2);
return restaurents;
}
}

If I understand your question correctly:
public ActionResult Search(string q)
{
Helpers Helpers = new Helpers();
var restaurants = Helpers.getRestaurant(q);
if (restaurants.Count() == 0) {
// do something
} else {
// do something else
}
return View("_RestaurantSearchResults", restaurants);
}
Take a look here: http://msdn.microsoft.com/en-us/library/bb351562%28v=vs.110%29.aspx. This goes over all the methods in the IQueryable<T> interface.
Oftentimes when you are looking for how to work with a certain part of the .NET Framework, C#, or others' code, the documentation is the best first place to go to.

simply check your result count for it.
public ActionResult Search(string q)
{
Helpers Helpers = new Helpers();
var restaurants = Helpers.getRestaurant(q);
if(restaurants.Count()>0)
{
return View("_RestaurantSearchResults", restaurants);
}
else
{
ViewBag.Message="No result found";
return View("_RestaurantSearchResults");
}
}
And just check if ViewBag.Message is available or not in View.

Try this
if (restaurants.Count() != 0)
{
//non-zero thing
}
else
{
//zero thing
}

Related

Business logic in ASP.NET Core MVC

This is my first question here so I'm really open for opinions, I searched a lot about ASP.NET Core MVC and still I don't have enough answers if I'm writing code in right way.
In many tutorials on Youtube I saw people create ASP.NET Core MVC applications with CRUD operations but there were just simple without any logic and all code was in controllers.
What if I want add some logic for example checking if my record already exists in the database? Where should I put this?
I have class Patient and I want add patient to database so I got in patient controller this :
public async Task<IActionResult> Create([Bind("PatientId,Name,Surname,Pesel")] Patient patient)
{
if (ModelState.IsValid)
{
String result = facade.Add_patient(patient);
if (result == "Patient added")
{
_context.Add(patient);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
else
{
ViewBag.Message = "Patient exists";
return View();
}
}
}
Facade is my class in model folder where I have this :
public class Facade
{
private Database_controller _context;
public Facade(Database_controller context)
{
_context = context;
}
private List<Patient> patients = new List<Patient>();
public List<Patient> Patients { get => patients; set => patients = value; }
public void updatedata()
{
patients = _context.Patients.ToList();
}
public string Add_patient(Patient patient)
{
Patient Patient = new Patient();
Patient.Name = patient.Name;
Patient.Surname = patient.Surname;
Patient.Pesel = patient.Pesel;
String if_is = addpacjent(Patient);
if (!"Is".Equals(if_is))
{
return "Patient added";
}
else
{
return "Patient exists";
}
}
public String addpacjent(Patient val)
{
bool if_is = patients.Contains(val);
if (if_is == true)
{
return ("Is");
}
else
{
patients.Add(val);
return null;
}
}
}
In Patient class is override method equals for checking
public override bool Equals(Object ob)
{
String Name = Surname;
String Name2 = ((Patient)ob).Surname;
String Pesel1 = Pesel;
String Pesel2 = ((Patient)ob).Pesel;
bool a = Name.Equals(Name2);
if (Pesel2 != "0")
{
bool b = Pesel1.Equals(Pesel2);
bool c = false;
if (a && b == true)
{
c = true;
}
return c;
}
else
return a;
}
Is it the right way? Should I have method _context.Add(patient) in Facade or controller? Where should I check existence in database?
I already have application which I want write in .NET Core in Winforms so I want use as many as possible code from Winforms classes so it's why I started coding like this in ASP.NET Core MVC
The easiest way is to use Any(),this is because Any() will return as soon as it finds a match.
Like my following:
public IActionResult Test()
{
//Simulation data:
var patient = new Patient
{
Name="AA",
SumName="AA-aa",
Pesel="23"
};
//Here you can add your conditions.
if (!_context.Patients.Any(o => o.Name == patient.Name&&o.SumName==patient.SumName&&o.Pesel==patient.Pesel))
{
_context.Add(patient);
_context.SaveChanges();
return RedirectToAction(nameof(Index));
}
else
{
ViewBag.Message = "Patient exists";
return View();
};
}
Below is the demo data in my database:
Sample effect display:

More concise/idiomatic way of continuing with code if true is returned or exiting if false

I have a few items -- let's just call them itemA, itemB, itemC, and itemD -- and I would like to validate each of them using a validation method I have written.
The validation method return type and signature is as follows:
public async Task<ValidationMessage> ValidateItem(MyClass item);
The ValidationMessage is a simple class:
public class ValidationMessage
{
public bool Success { get; set; }
public string ErrorMessage { get; set; }
}
To validate each item, currently I have the following code:
ValidationMessage result = new ValidationMessage();
result = await this.ValidateItem(itemA);
if (!result.Success)
{
return result;
}
result = await this.ValidateItem(itemB);
if (!result.Success)
{
return result;
}
result = await this.ValidateItem(itemC);
if (!result.Success)
{
return result;
}
result = await this.ValidateItem(itemD);
return result;
As you can see, as soon as one of the items fails the validation method (meaning result.Success == false), I return and do not continue with validating the rest of them.
I think it's kind of tedious/ugly to have the repeated assignments to result and the repeated if statements. I was hoping there is some existing c# class/construct (perhaps LINQ can help) to write this more concisely. I made up the following to demonstrate what I'm sort of thinking:
ValidationMessage result = new ValidationMessage();
result = await this.ValidateItem(itemA).ContinueConditional(
(r => r.Success) => await this.ValidateItem(itemB).ContinueConditional(
(r => r.Success) => await this.ValidateItem(itemC).ContinueConditional(
(r => r.Success) => await this.ValidateItem(itemD))));
return result;
Basically, the return value of this.ValidateItem(itemA) is assigned to result and then this value goes into the ContinueConditional. If the result, r, has Success == true, then continue with validating itemB, and so on. If it's not successful, then exit out of that code and go straight to the return statement at the bottom, thus returning the item which failed the validation. If all items are validated then it will go to that return statement anyway.
I apologize for the long wall of text, especially if the c# construct already exists and is obvious. I appreciate any help with this.
Note: I have simplified my real example for the sake of posting this. One important part of the simplification is that itemA, itemB, itemC, and itemD are not the same type, despite referring to them as MyClass in the method signature above. So I can't just put them in a list and use LINQ. This also means I actually have different validation methods to accept the various items I have, but I didn't want to explain all that at the top in case it over-complicates things. The important part is that they all return ValidationMessage.
What about inverting the logic around the check for success/failure?
ValidationMessage result = await this.ValidateItem(itemA);
if (result.Success) result = await this.ValidateItem(itemB);
if (result.Success) result = await this.ValidateItem(itemC);
if (result.Success) result = await this.ValidateItem(itemD);
return result;
How about this? You can extend it to as many elements as you want.
var validationRules = new List<Func<Task<bool>>>(){
() => ValidateItem(itemA),
() => ValidateItem(itemB),
() => ValidateItem(itemC),
() => ValidateItem(itemD),
};
ValidationMessage result = new ValidationMessage();
foreach(var validationRule in validationRules)
{
result = await validationRule();
if(!result)
return result;
}
return result;
You could use FluentValidation to create a custom rule to loop through a list of models to validate. This is more overhead than the other answers but it's a good approach with clean readable code.
First define your shared model
public class YourSharedModel()
{
List<MyClass> Models = new List<MyClass>();
}
Define the validator:
public class SharedModelValidator : AbstractValidator<YourSharedModel>
{
public SharedModelValidator()
{
CustomRule(BeValid)
}
public bool BeValid(ValidationErrors<YourSharedModel> validationFailures, YourSharedModel sharedModel, ValidationContext<YourSharedModel> validationContext)
{
for (var m in sharedModel.Models)
{
var result = YourValidationMethod(m);
if (!result.Success)
{
validationFailures.AddFailureFor(x => m, result.ErrorMessage);
return false;
}
}
return true;
}
private YourValidationMethod(MyClass model)
{
// the code you have that actually validates
}
}
Implementation would be something like:
var yourSharedModel = new YourSharedModel();
yourSharedModel.Models.Add(itemA);
yourSharedModel.Models.Add(itemB);
// etc
var validator = new SharedModelValidator();
var results = validator.Validate(yourSharedModel);
if (!results.IsValid)
{
// do something with results.Errors
}
You could also keep all your errors and return false after the loop so that you get all the errors at once rather than one by one on submission, of course that's assuming a form post from a web application. Makes for a better user friendly experience.
You could use an interface and then add your items to a list that you foreach through:
ValidationMessage Test()
{
List<IValidatable> items = new List<IValidatable>();
MyClass1 item1 = new MyClass1();
MyClass2 item2 = new MyClass2();
items.Add(item1);
items.Add(item2);
ValidationMessage result = null;
foreach (var i in items)
{
result = i.ValidateItem();
if (!result.Success) break;
}
return result;
}
interface IValidatable
{
ValidationMessage ValidateItem();
}
public class ValidationMessage
{
public bool Success { get; set; }
public string ErrorMessage { get; set; }
}
public class MyClass1 : IValidatable
{
public ValidationMessage ValidateItem()
{
return new ValidationMessage();
}
}
public class MyClass2 : IValidatable
{
public ValidationMessage ValidateItem()
{
return new ValidationMessage();
}
}
Another (perhaps anorthodox) way to do it is to overload the && operator on ValidationMessage:
public class ValidationMessage
{
public bool Success { get; set; }
public string ErrorMessage { get; set; }
public static ValidationMessage operator &(ValidationMessage message1, ValidationMessage message2)
{
return message1.Success ? message2 : message1;
}
public static ValidationMessage operator |(ValidationMessage message1, ValidationMessage message2)
{
return message1.Success ? message1 : message2;
}
public static bool operator true(ValidationMessage message)
{
return message.Success;
}
public static bool operator false(ValidationMessage message)
{
return !message.Success;
}
}
Then you can do:
return (await this.ValidateItem(ItemA)) &&
(await this.ValidateItem(ItemB)) &&
(await this.ValidateItem(ItemC)) &&
(await this.ValidateItem(ItemD));

How to return array from database in c#

I want to return my result as array list. My code looks like this:
public Person Get(string doctorCode)
{
using (PharmaOCEAN_LTEntities entities = new PharmaOCEAN_LTEntities())
{
return entities.Person.FirstOrDefault(e => e.DoctorLicenseNumber == doctorCode);
}
}
Some guy informed me that selected (all) result will be an array, so I tried this way, but im getting an error with select statement:
public IList<Person> Get(string doctorCode)
{
using (PharmaOCEAN_LTEntities entities = new PharmaOCEAN_LTEntities())
{
return entities.Person.Select<Person>(e => e.DoctorLicenseNumber == doctorCode);
}
}
any opinions?
Yeah sure you can!
As a array:
public Person[] Get(string doctorCode)
{
using (PharmaOCEAN_LTEntities entities = new PharmaOCEAN_LTEntities())
{
return entities.Person.Where(e => e.DoctorLicenseNumber == doctorCode).ToArray();
}
}
As a list:
public IEnumerable<Person> Get(string doctorCode)
{
using (PharmaOCEAN_LTEntities entities = new PharmaOCEAN_LTEntities())
{
return entities.Person.Where(e => e.DoctorLicenseNumber == doctorCode).ToList();
}
}
not sure if it compiles, but you get the message :)
Can you provide info error that you get?
Don't you have to add ToList() at the end of select statement?

Passing string from model that is created on certain condition

I just happaned to have some troubles.
I have a model with a function
public class Profile
{
public void PrintResult()
{
if(1 == 1)
{
Console.WriteLine("equals 1");
if(2 == 2)
{
Console.WriteLine("equals 2");
}
}
else
{
Console.WriteLine("error");
}
}
}
this is the controller:
public ActionResult Index()
{
Profile p = new Profile();
p.PrintResult();
return View();
}
Well, I know that console.writeline or response.write.
So, my question is: how could I make those console.writeline to things like
string s = "Equals 2";
instead of console.writelines which does not working obviously and then call it somehow both equals 1 and equals 2 show in the view.
Been googling for quite long and couldn't find an answer.
If you need more info to help me, tell me #_ #
Instead of console.writeline, you have to return comma seperated string Or list of string
public List<string> PrintResult()
{
var listItems = new List<string>();
if (1 == 1)
{
listItems.Add("equal 1");
if (2 == 2)
{
listItems.Add("equal 2");
}
}
else
{
listItems.Add("error");
}
return listItems;
}
Return a comma separated list from your model in this case(Though i do not support coding such kind of models.Think this is for your practise).
public class Profile
{
public string PrintResult()
{
string strSample="";
if(1 == 1)
{
if(strSample=="")
{
strSample="equals 1";
}
else
{
strSample+=","+"equals1";
}
if(2 == 2){
if(strSample=="")
{
strSample="equals 2";
}
else
{
strSample+=","+"equals2";
}
|
}else
{
if(strSample=="")
{
strSample="error";
}
else
{
strSample+=","+"error";
}
}
}
}
Now In your controller pass this string returned from the model to your view as follows
public ActionResult Index()
{
Profile p = new Profile();
string sample=p.PrintResult();
return View((object)sample);
}
Now in your Index View, make the view as strongly typed to a string like below
#model string
<h1>#Model</h1>

Implementing Strategy pattern instead of several if statements

I have this method with lot of if statements, in which I'm filtering SharePoint list based on employee position.The result is query string which is passed as parameter to another method QuerySPList.
public List<Phone> GetListOfPhones(Employee emp)
{
List<Phone> records = new List<Phone>();
string query = string.Empty;
if (emp.Positions.Count == 1 && emp.Positions[0] == "Regular")
{
query = "";// some querystring
}
if (emp.Positions.Count == 1 && emp.Positions[0] == "OfficeDirector")
{
query = "";// some querystring
}
if (emp.Positions.Count == 1 && emp.Positions[0] == "Admin")
{
query = "";// some querystring
}
if (emp.Positions.Count == 2 && emp.Positions.Contains("Regular") && emp.Positions.Contains("OfficeDirector"))
{
query = "";// some querystring
}
var rawItems = QuerySPList(query);
foreach (SPListItem item in rawItems)
{
//business logic
}
return records;
}}
I've read that with implementing strategy pattern we can avoid messy code with lot of if's , however , I'm new to developing , and design patterns , so I need little help with this one,so if someone can guide me what should I do and give me advice , feel free to answer my question.I have idea , but I think that I'm going in the wrong direction.
Idea is to create interface IRoleHandler and than implement it to 3 classes , for example RoleAdmin ,RoleRegular,RoleOfficeDirector.Something like this :
public interface IRoleHandler<T>
{
string handleRole(T obj);
}
public class RoleAdmin:IRoleHandler<Employee>
{
public string handleRole(Employee emp)
{
if (emp.Positions.Count == 1 && emp.Positions[0] == "Admin")
{
//return some string query
}
}
}
Then idea is to create dictionary,something like this :
Dictionary<string, IRoleHandler<Employee>> strategyHandlers = new Dictionary<string, IRoleHandler<Employee>>();
strategyHandlers.Add("Admin", new RoleAdmin());
strategyHandlers.Add("Regular", new RoleRegularUser());
Firstly, I think you need to be less concerned with the 'internal structure' of the Strategy Pattern and more concerned with its design goal/use.
https://en.wikipedia.org/wiki/Strategy_pattern
the strategy pattern (also known as the policy pattern) is a software design pattern that enables an algorithm's behavior to be selected at runtime. The strategy pattern
defines a family of algorithms,
encapsulates each algorithm, and
makes the algorithms interchangeable within that family.
To me, it looks like you are actually intending to "create" a string, based on some input value.
Therefore you would likely want to use one of the Creational patterns
My suggestion would be likely be Factory Pattern, or possibly Builder pattern. (Both linked in the creational patterns link)
private string BuildQueryByEmployee(Employee emp) {
// create your builder
EmployeeQueryBuilder mBuilder = new EmployeeQueryBuilder ();
// add # of positions
mBuilder.addPositionCount(emp.Positions.Count);
// add each position
for (int i =0 ; i < emp.Positions.Count; i++ ){
mBuilder.addPosition(emp.Positions[i]);
}
// 'build' your query.
// and return the query as a string.
return mBuilder.buildQuery();
}
Then inside your EmployeeQueryBuilder class, you handle the complexity of how to build your query based on the # of positions, and what they are.
Secondly, Here are some links that might be of use to you.
https://en.wikipedia.org/wiki/Software_design_pattern (General disc. of Patterns)
https://en.wikipedia.org/wiki/Design_Patterns (The "Gang of Four" book, essentially the first book on design patterns, and worth reading a few times, and writing each pattern out by hand a few times until you are comfortable with them, this alone will boost your coding ability by 2~3x if you haven't used patterns before, The examples in this book are somewhat out of date, since its motivating factor is writing a Text Editor... but still a 'classic', well worth knowing)
http://www.cs.wustl.edu/~schmidt/POSA/POSA2/ (One of the first books on patterns that have to deal with Concurrency) (POSA = Pattern Oriented Software Architecture) (might be overkill for now, but 'good to know about' in general)
I don't think strategy pattern is what you want. I would just refactor your code to extract the ifs to another method.
public List<Phone> GetListOfPhones(Employee emp)
{
List<Phone> records = new List<Phone>();
string query = BuildQueryByEmployeePosition(emp);
var rawItems = QuerySPList(query);
foreach (SPListItem item in rawItems)
{
//business logic
}
return records;
}
private string BuildQueryByEmployeePosition(Employee emp)
{
if (emp.Positions.Count == 1 && emp.Positions[0] == "Regular")
return "";// some querystring
if (emp.Positions.Count == 1 && emp.Positions[0] == "OfficeDirector")
return "";// some querystring
if (emp.Positions.Count == 1 && emp.Positions[0] == "Admin")
return "";// some querystring
if (emp.Positions.Count == 2 && emp.Positions.Contains("Regular") && emp.Positions.Contains("OfficeDirector"))
return "";// some querystring
return ""; // some default query
}
Here is a link to a great explanation of strategy pattern
(with a real example of a sort algorithm).
It's great to see that you are new to programming and is studying patterns, but
beware: using them when they are not needed is an anti-pattern.
In my opition it is better you use a kind of STATE PATTERN with COMPOSITE.
Example:
public abstract class Position
{
public abstract List<int> ListOfPhones();
}
public class Employer
{
public virtual IList<Position> CurrentPositions { get; set; }
}
public class Manager : Employer
{
public Manager(List<Position> positions)
{
this.CurrentPositions = positions;
}
public IEnumerable<int> GetNumbers()
{
foreach (Position position in this.CurrentPositions)
foreach (var number in position.ListOfPhones())
yield return number;
}
}
Code above is incomplete, just for you get the ideia.
I agree with mawalker, you don't need strategy pattern as you have the same behavior for all cases. What do you need is some kind of creational patterns. I would refactor your code using Builder and Chain of Responsibility patterns.
1) Implement base class:
public abstract class EmployeeHandler
{
private readonly EmployeeHandler _nextHandler;
protected EmployeeHandler(EmployeeHandler nextHandler)
{
_nextHandler = nextHandler;
}
public string BuildQuery(Employee emp)
{
if (CanHandle(emp))
{
return GetQuery(emp);
}
if (_nextHandler == null)
{
return string.Empty;
}
return _nextHandler.BuildQuery(emp);
}
protected abstract string GetQuery(Employee emp);
protected abstract bool CanHandle(Employee emp);
}
2) Define concrete implementations:
public class RegularEmployeeHandler : EmployeeHandler
{
public RegularEmployeeHandler(EmployeeHandler nextHandler) : base(nextHandler) {
}
protected override bool CanHandle(Employee emp)
{
return emp.Positions.Count == 1 && emp.Positions[0] == "Regular";
}
protected override string GetQuery(Employee emp)
{
return "some regular query";
}
}
public class OfficeDirectorEmployeeHandler : EmployeeHandler
{
public OfficeDirectorEmployeeHandler(EmployeeHandler nextHandler) : base(nextHandler) {
}
protected override bool CanHandle(Employee emp)
{
return emp.Positions.Count == 1 && emp.Positions[0] == "OfficeDirector";
}
protected override string GetQuery(Employee emp)
{
return "some office director query";
}
}
public class AdminEmployeeHandler : EmployeeHandler
{
public AdminEmployeeHandler(EmployeeHandler nextHandler) : base(nextHandler) {
}
protected override bool CanHandle(Employee emp)
{
return emp.Positions.Count == 1 && emp.Positions[0] == "Admin";
}
protected override string GetQuery(Employee emp)
{
return "some admin query";
}
}
public class RegularAndOfficeDirectorEmployeeHandler : EmployeeHandler
{
public RegularAndOfficeDirectorEmployeeHandler(EmployeeHandler nextHandler) : base(nextHandler) {
}
protected override string GetQuery(Employee emp)
{
return "some regular and director query";
}
protected override bool CanHandle(Employee emp)
{
return emp.Positions.Count == 2 && emp.Positions.Contains("Regular") && emp.Positions.Contains("OfficeDirector");
}
}
3) And finally you main class will changed like this:
public class YouMainClass
{
private readonly EmployeeHandler _firstHandler;
public YouMainClass()
{
var regularHandler = new RegularEmployeeHandler(null);
var officeDirectorHandler = new OfficeDirectorEmployeeHandler(regularHandler);
var adminHandler = new AdminEmployeeHandler(officeDirectorHandler);
_firstHandler = new RegularAndOfficeDirectorEmployeeHandler(adminHandler);
}
public List<Phone> GetListOfPhones(Employee emp, IQueryBuilder queryBuilder)
{
List<Phone> records = new List<Phone>();
string query = _firstHandler.BuildQuery(emp);
var rawItems = QuerySPList(query);
foreach (SPListItem item in rawItems)
{
//business logic
}
return records;
}
}

Categories