Web API controller returning boolean - model-view-controller

I have a Web API where one of the methods in a controller return true or false when validating user id which is a string of numbers. I do no have an actual database yet, so I sort of mocked up the set of values in the repository.
Below is my code:
My repository class:
public class myRepository
{
public myClasses.Employee[] GetAllEmployees()
{
return new myClasses.Employee[]
{
new myClasses.Employee
{
empId="111111",
empFName = "Jane",
empLName="Doe"
},
new myClasses.Employee
{
empId="222222",
empFName = "John",
empLName="Doe"
}
};
}
public bool VerifyEmployeeId(string id)
{
myClasses.Employee[] emp = new myClasses.Employee[]
{
new myClasses.Employee
{
empId="111111",
empFName = "Jane",
empLName="Doe"
},
new myClasses.Employee
{
empId="222222",
empFName = "John",
empLName="Doe"
}
};
for (var i = 0; i <= emp.Length - 1; i++)
{
if (emp[i].empId == id)
return true;
}
return false;
}
}
and my model class:
public class myClasses
{
public class Employee
{
public string empId { get; set; }
public string empFName { get; set; }
public string empLName { get; set; }
}
}
and here is my controller:
public class myClassesController : ApiController
{
private myRepository empRepository;
public myClassesController()
{
this.empRepository = new myRepository();
}
public myClasses.Employee[] GetEmployees()
{
return empRepository.GetAllEmployees();
}
public bool VerifyEmployee(string id)
{
return empRepository.VerifyEmployeeId(string id);
}
}
Now when i compile it I get an error:
} expected
Type or namespace definition, or end-of-file expected
; expected
in line
return empRepository.VerifyEmployeeId(string id);
of my controller.
My question is using boolean the best way to return Success or Failure from Web API method or is there a better way? and also why am I getting this error. I am new to Web API

The compile error is caused by this;
return empRepository.VerifyEmployeeId(string id);
You should rewrite to:
return empRepository.VerifyEmployeeId(id);
You don't have you specify the type of the argument when calling a function.
About returning true or false; if you intend to only check whether the employee is valid or not, I should leave it this way. If you plan to use that employee data more you could rewrite that function so it returns the actual employee itself, and return 404: Not Found when the Employee is not found for instance.

Related

Mediator Api call failing

I'm trying to make a simple request using mediator and .net core. I'm getting an error that I am not understanding. All I'm trying to do is a simple call to get back a guid.
BaseController:
[Route("api/[controller]/[action]")]
[ApiController]
public class BaseController : Controller
{
private IMediator _mediator;
protected IMediator Mediator => _mediator ?? (_mediator = HttpContext.RequestServices.GetService<IMediator>());
}
Controller:
// GET: api/Customer/username/password
[HttpGet("{username}/{password}", Name = "Get")]
public async Task<ActionResult<CustomerViewModel>> Login(string username, string password)
{
return Ok(await Mediator.Send(new LoginCustomerQuery { Username = username,Password = password }));
}
Query:
public class LoginCustomerQuery : IRequest<CustomerViewModel>
{
public string Username { get; set; }
public string Password { get; set; }
}
View Model:
public class CustomerViewModel
{
public Guid ExternalId { get; set; }
}
Handler:
public async Task<CustomerViewModel> Handle(LoginCustomerQuery request, CancellationToken cancellationToken)
{
var entity = await _context.Customers
.Where(e =>
e.Username == request.Username
&& e.Password == Encypt.EncryptString(request.Password))
.FirstOrDefaultAsync(cancellationToken);
if (entity.Equals(null))
{
throw new NotFoundException(nameof(entity), request.Username);
}
return new CustomerViewModel
{
ExternalId = entity.ExternalId
};
}
This is the exception I am getting:
Please let me know what else you need to determine what could be the issue. Also, be kind I have been away from c# for a while.
Thanks for the info it was the missing DI. I added this
// Add MediatR
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPreProcessorBehavior<,>));
services.AddMediatR(typeof(LoginCustomerQueryHandler).GetTypeInfo().Assembly);
and we are good to go.

Parsing API response in Xamarin form

I am new to xamarin. I am trying to get data from php api but it doesn't give me any data or error kindly check. URL is
http://mehdibalti.000webhostapp.com/xamrin/getall.php
response is .. [{"Id":"1","Name":"Mehdi","Department":"Balti"},{"Id":"2","Name":"Mehdi","Department":"Syntecx"}]
and i did like this
public class EmployeeServices
{
public EmployeeServices()
{
}
public async Task<List<EmployeeModel>> getEmployeeAsyn(){
RestClient<EmployeeModel> resclient = new RestClient<EmployeeModel>();
var list =await resclient.GetTodoItemsAsync();
return list;
}
}
}
this is my resClient Class
public async Task<List<EmployeeModel>> GetTodoItemsAsync()
{
var httpClient = new HttpClient();
var response = await httpClient.GetStringAsync(getAllUrl);
response = response.Replace("\"", "");
var todoItems = JsonConvert.DeserializeObject<List<EmployeeModel>>(response);
return todoItems;
}
this is Model class
public class EmployeeModel
{
public string Id { get; set; }
public string Name { get; set; }
public string Department { get; set; }
}
but it did not return any list
The result API is giving you is not a list. Use stuff like http://json2csharp.com/
to investigate json you are getting.

Repository Pattern and Azure Table Storage(???)

While doing the following simple example, I found the following difficulties
As the title says, I am intending to use the Repository pattern while I am storing data in the Azure table storage.now I have couple of classes, Repository.cs, IRepository.cs, DataContext.cs and the Controller.
During my reading I found some info and been doing as follows.
IRepository.cs
public interface IRepository<T> where T: TableServiceEntity
{
T GetById(int Id);
IQueryable<T> GetAll();
}
and the DataContext.cs
public class DataContext<T>:TableServiceContext where T:TableServiceEntity
{
public DataContext(CloudStorageAccount storageaccount, StorageCredentials credentials)
: base(storageaccount.TableEndpoint.AbsoluteUri, credentials)
{
// _storageAccount = storageaccount;
var storageAccount = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue(KEY_STORAGE));
storageAccount.CreateCloudTableClient().CreateTableIfNotExist(tableName);
}
public IQueryable<T> DeviceTable
{
get { return CreateQuery<T>(tableName); }
}
}
plus some part of the controller(I have already data in the table which I created before)
public class DeviceMeController : Controller
{
private IRepository<Entity>_repository;
public Controller() : this(new Repository<Entity>())
{
}
public Controller(IRepository<Entity> repository)
{
_repository = repository;
}
public ActionResult Index()
{
var List = _repository.GetAll();
return View(deviceList);
}
and the the Implementation of the interface Reposistory.cs, here is where I have an error and got lost somewhere
public class Repository<T>:IRepository<T> where T:TableServiceEntity
{
private DataContext<T> _serviceContext;
// here get tablename as pararameter;
// so the Enities call this function
public Repository()
{
// the same context for multiple tables ?
}
// perhaps it should take the table Name
public void Add(T item)
{
_serviceContext.AddObject(TableName,item);
_serviceContext.SaveChangesWithRetries();
}
public IQueryable<T> GetAll()
{
var results = from c in _serviceContext.Table
select c;
return results;
Error is about the null reference, the debugger shows the variable results is null?
In the end I need to know few things.
what should I do in the Repository.cs constructor? I believe the Datacontext.cs class has to be in a separate class ...
any Hint here
Hy,
first of all I presume you left out some code, because I don't see how you get your context in your repository. But supposing you do set it correctly, (injection?) taking into account the way you desinged your datacontext the repository doesn't need to know the table name because it is set in the following lines of code:
public IQueryable<T> DeviceTable
{
get { return CreateQuery<T>(Constants.DeviceTableName); }
}
So when you create a query based on the IQueryable DeviceTable, the table name is already set.
The thing is I don't see the need for your context class, especially as it can only bring over a single entity type (it is generic and based on an entity).
A basic layout of my Repository for Azure Table Storage is:
public abstract class CloudRepository<TEntity> : ICloudRepository<TEntity>
{
private TableServiceContext _tableServiceContext;
private string _tableName;
public string TableName
{
get { return _tableName ?? ( _tableName = typeof(TEntity).Name.Replace("Entity", string.Empty).ToLower()); }
}
public CloudStorageAccount StorageAccount
{
get
{
return CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("StorageConnectionString"));
}
}
public CloudTableClient TableClient
{
get
{
CloudTableClient cloudTableClient = StorageAccount.CreateCloudTableClient();
cloudTableClient.CreateTableIfNotExist(TableName);
return cloudTableClient;
}
}
public TableServiceContext ServiceContext
{
get
{
return _tableServiceContext ?? (_tableServiceContext = TableClient.GetDataServiceContext());
}
}
public IEnumerable<TEntity> FindAll()
{
return ServiceContext.CreateQuery<TEntity>(TableName).ToList();
}
}
Hope this helps you.

How to unit test child validators with When() condition with FluentValidation.TestHelper

The extension method .ShouldHaveChildValidator() in the FluentValidation.TestHelper namespace doesn't have an overload that takes the model. How do I then test that the child validators are set up correctly when using a When() clause like in the following example?
E.g.
public class ParentModel
{
public bool SomeCheckbox { get; set; }
public ChildModel SomeProperty { get; set; }
}
public class ParentModelValidator : AbstractValidator<ParentModel>
{
RuleFor(m => m.SomeProperty)
.SetValidator(new ChildModelValidator())
.When(m => m.SomeCheckbox);
}
I want to Assert that if SomeCheckbox is true, then the child validator is present, and if SomeCheckbox is false, then the child validator isn't present.
I have the following so far in the unit test:
ParentModelValidator validator = new ParentModelValidator();
validator.ShouldHaveChildValidator(
m => m.SomeProperty,
typeof(ChildModelValidator));
but that doesn't take into account the .When() condition.
I notice other methods in the FluentValidation.TestHelper namespace such as .ShouldHaveValidationErrorFor() have an overload that takes the model, so it's easy to test a simple property type with a When() clause by setting up a model that satisfies the precondition.
Any ideas?
Here's a snippet of how I achieve this:
public class ParentModelSimpleValidator : AbstractValidator<ParentModel>
{
public ParentModelSimpleValidator()
{
When(x => x.HasChild, () =>
RuleFor(x => x.Child)
.SetValidator(new ChildModelSimpleValidator()));
}
}
public class ChildModelSimpleValidator : AbstractValidator<ChildModel>
{
public ChildModelSimpleValidator()
{
RuleFor(x => x.ChildName)
.NotEmpty()
.WithMessage("Whatever");
}
}
Here's the relevant simplified models:
[Validator(typeof(ParentModelSimpleValidator))]
public class ParentModel
{
public bool HasChild { get { return Child != null; } }
public ChildModel Child { get; set; }
}
[Validator(typeof(ChildModelSimpleValidator))]
public class ChildModel
{
public string ChildName { get; set; }
public int? ChildAge { get; set; }
}
Here's a sample unit test:
[TestMethod]
public void ShouldValidateChildIfParentHasChild()
{
var validator = new ParentModelSimpleValidator();
var model = new ParentModel
{
ParentName = "AABBC",
Child = new ChildModel { ChildName = string.Empty }
};
validator.ShouldHaveErrorMessage(model, "Whatever");
}
very late to the game here, but I just started using FluentValidation and that was my solution
public class ParentValidator: AbstractValidator<ParentModel>
{
public ParentValidator()
{
// other rules here
// use == for bool?
When(model => model.SomeBoolProperty == false, () => RuleFor(model => model.ChildClass).SetValidator(new ChildClassValidator()));
}
}
public class ChildClassValidator: AbstractValidator<ChildClass>
{
public ChildClassValidator()
{
this
.RuleFor(model => model.SomeProperty).NotNull();
}
}
then the test is
[TestMethod]
public void ParentValidator_should_have_error_in_child_class_property_when_bool_is_false_on_parent()
{
// Arrange - API does not support typical unit test
var validator = new ParentValidator()
var foo = new ParentModel() { SomeBoolProperty = false };
foo.ChildClass.SomeProperty = null;
// Act
var result = validator.Validate(foo);
// Assert - using FluentAssertions
result.Errors.Should().Contain(err => err.PropertyName == "ChildClass.SomeProperty");
}

Linq - reuse expression on child property

Not sure if what I am trying is possible or not, but I'd like to reuse a linq expression on an objects parent property.
With the given classes:
class Parent {
int Id { get; set; }
IList<Child> Children { get; set; }
string Name { get; set; }
}
class Child{
int Id { get; set; }
Parent Dad { get; set; }
string Name { get; set; }
}
If i then have a helper
Expression<Func<Parent,bool> ParentQuery() {
Expression<Func<Parent,bool> q = p => p.Name=="foo";
}
I then want to use this when querying data out for a child, along the lines of:
using(var context=new Entities.Context) {
var data=context.Child.Where(c => c.Name=="bar"
&& c.Dad.Where(ParentQuery));
}
I know I can do that on child collections:
using(var context=new Entities.Context) {
var data=context.Parent.Where(p => p.Name=="foo"
&& p.Childen.Where(childQuery));
}
but cant see any way to do this on a property that isnt a collection.
This is just a simplified example, actually the ParentQuery will be more complex and I want to avoid having this repeated in multiple places as rather than just having 2 layers I'll have closer to 5 or 6, but all of them will need to reference the parent query to ensure security.
If this isnt possible, my other thought was to somehow translate the ParentQuery expression to be of the given type so effectively:
p => p.Name=="foo";
turns into:
c => c.Dad.Name=="foo";
but using generics / some other form of query builder that allows this to retain the parent query and then just have to build a translator per child object that substitutes in the property route to the parent.
EDIT:
Following on from comments by #David morton
Initially that looks like I can just change from Expression to a delegate function and then call
.Where(ParentQuery()(c.Dad));
However I am using this in a wider repository pattern and cant see how I can use this with generics and predicate builders - I dont want to retrieve rows from the store and filter on the client (web server in this case). I have a generic get data method that takes in a base expression query. I then want to test to see if the supplied type implements ISecuredEntity and if it does append the securityQuery for the entity we are dealing with.
public static IList<T> GetData<T >(Expression<Func<T, bool>> query) {
IList<T> data=null;
var secQuery=RepositoryHelperers.GetScurityQuery<T>();
if(secQuery!=null) {
query.And(secQuery);
}
using(var context=new Entities.Context()) {
var d=context.GetGenericEntitySet<T>();
data=d.ToList();
}
return data;
}
ISecuredEntity:
public interface ISecuredEntity : IEntityBase {
Expression<Func<T, bool>> SecurityQuery<T>();
}
Example Entity:
public partial class ExampleEntity: ISecuredEntity {
public Expression<Func<T, bool>> SecurityQuery<T>() {
//get specific type expression and make generic
Type genType = typeof(Func<,>).MakeGenericType(typeof(ExampleEntity), typeof(bool));
var q = this.SecurityQuery(user);
return (Expression<Func<T, bool>>)Expression.Lambda(genType, q.Body, q.Parameters);
}
public Expression<Func<ExampleEntity, bool>> SecurityQuery() {
return e => e.OwnerId==currentUser.Id;
}
}
and repositoryHelpers:
internal static partial class RepositoryHelpers {
internal static Expression<Func<T, bool>> SecureQuery<T>() where T : new() {
var instanceOfT = new T();
if (typeof(Entities.ISecuredEntity).IsAssignableFrom(typeof(T))) {
return ((Entities.ISecuredEntity)instanceOfT).SecurityQuery<T>();
}
return null;
}
}
EDIT Here is the (eventual) solution
I ended up going back to using expressions, and using LinqKit Invoke. Note: for EF I also had to call .AsExpandable() on the entitySet
The key part is being able to call:
Product.SecureFunction(user).Invoke(pd.ParentProduct);
so that I can pass in the context into my parent query
My end classes look like:
public interface ISecureEntity {
Func<T,bool> SecureFunction<T>(UserAccount user);
}
public class Product : ISecureEntity {
public Expression<Func<T,bool>> SecureFunction<T>(UserAccount user) {
return SecureFunction(user) as Expression<Func<T,bool>>;
}
public static Expression<Func<Product,bool>> SecureFunction(UserAccount user) {
return f => f.OwnerId==user.AccountId;
}
public string Name { get;set; }
public string OwnerId { get;set; }
}
public class ProductDetail : ISecureEntity {
public Expression<Func<T,bool>> SecureFunction<T>(UserAccount user) {
return SecureFunction(user) as Expression<Func<T,bool>>;
}
public static Func<ProductDetail,bool> SecureFunction(UserAccount user) {
return pd => Product.SecureFunction(user).Invoke(pd.ParentProduct);
}
public int DetailId { get;set; }
public string DetailText { get;set; }
public Product ParentProduct { get;set; }
}
Usage:
public IList<T> GetData<T>() {
IList<T> data=null;
Expression<Func<T,bool>> query=GetSecurityQuery<T>();
using(var context=new Context()) {
var d=context.GetGenericEntitySet<T>().Where(query);
data=d.ToList();
}
return data;
}
private Expression<Func<T,bool>> GetSecurityQuery<T>() where T : new() {
var instanceOfT = new T();
if (typeof(Entities.ISecuredEntity).IsAssignableFrom(typeof(T))) {
return ((Entities.ISecuredEntity)instanceOfT).SecurityQuery<T>(GetCurrentUser());
}
return a => true; //returning a dummy query
}
}
Thanks for the help all.
You're overthinking it.
First, don't return an Expression<Func<Parent, bool>>, that'll require you to compile the expression. Return simply a Func<Parent, bool> instead.
Next, it's all in how you call it:
context.Children.Where(c => c.Name == "bar" && ParentQuery()(c.Dad));
context.Parents.Where(ParentQuery());

Resources