Api routes for multiple get methods - api

I have two Get methods in my api as below :
public IHttpActionResult GetCandidateProfilesByProfileID(long id)
{
......
}
and
public IHttpActionResult GetCandidatesBySearchCrietria( string FName= null,string LastName = null, Nullable<DateTime> DoB = null, string City = null,string zipCode = null, string stateID = null,string education = null,
{
...
}
How to configure routes for these? I am having issues invoking them with the default route.
Thanks,
Mahantesh

I assume you are using Web Api 2. You can use the Route attribute:
In order to make http attribute routing available you'll have to add the following line in App_Start\WebApiConfig.cs:
static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
}
}
And then add the route attribute to the method.
[HttpGet]
[Route("GetCandidateProfilesByProfileID")]
public IHttpActionResult GetCandidateProfilesByProfileID(long id)
{
......
}
[HttpGet]
[Route("GetCandidatesBySearchCrietria")]
public IHttpActionResult GetCandidatesBySearchCrietria( string FName= null,string LastName = null, Nullable<DateTime> DoB = null, string City = null,string zipCode = null, string stateID = null,string education = null)
{
...
}
Please note that certain parameters are required. If omitted this will result in Http 404 Not Found.
In asp.net Core you can use the HttpGet attribute:
[HttpGet("GetCandidateProfilesByProfileID")]
public IHttpActionResult GetCandidateProfilesByProfileID(long id)
{
......
}
[HttpGet("GetCandidatesBySearchCrietria")]
public IHttpActionResult GetCandidatesBySearchCrietria( string FName= null,string LastName = null, Nullable<DateTime> DoB = null, string City = null,string zipCode = null, string stateID = null,string education = null)
{
...
}

Related

Unique constraint not respected when inserting into SQL table with .NET Core framework

I try to make a register functionality for a REST API in .NET Core 5.
When I create a new user the unique index is not respected and it lets me insert a new user with the same email.
Also, if let's say this constraint would work, what should I get as a result if the insert fails?
[Table("users")]
[Index(nameof(Email), IsUnique = true)]
public class UserDAO
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
DbContext:
public class DatabaseContext : DbContext
{
public DatabaseContext(DbContextOptions<DatabaseContext> options) : base(options)
{
}
public DbSet<UserDAO> Users { get; set; }
}
And the code from the Provider that inserts the user(it should return -1 if the insert fails):
public int createUser(string firstName, string lastName, DateTime dateOfBirth, string email, string password)
{
UserDAO user = new UserDAO
{
FirstName = firstName,
LastName = lastName,
DateOfBirth = dateOfBirth,
Email = email,
Password = password
};
_dbContext.Users.Add(user);
_dbContext.SaveChanges();
return user.Id;
}

Swagger Swashbuckle Asp.NET Core: show details about every enum is used

I have the following enum:
public enum TicketQuestionType
{
General = 1,
Billing = 2,
TMS = 3,
HOS = 4,
DeviceManagement = 5
}
and model class:
public class TicketCreateApi
{
public string Subject { get; set; }
public TicketQuestionType QuestionType { get; set; } = TicketQuestionType.General;
public TicketType Type { get; set; } = TicketType.Problem;
public TicketStatus Status { get; set; } = TicketStatus.New;
public TicketPriority Priority { get; set; } = TicketPriority.Normal;
public string Description { get; set; }
public List<string> Attachments { get; set; }
public int? DeviceId { get; set; }
public int? DriverId { get; set; }
}
my API method uses it:
Task<IActionResult> Create(TicketCreateApi model);
Swagger generates the following:
and this:
so, we can see only default value and no way to see available list of enum (names and values).
I would like to show it. How to do it?
we can see only default value and no way to see available list of enum
(names and values). I would like to show it. How to do it?
To display the enums as strings in swagger, you configure the JsonStringEnumConverter, adding the following line in ConfigureServices :
services.AddControllers().AddJsonOptions(options =>
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));
The output as below:
If you want to display the enums as stings and int values, you could try to create a EnumSchemaFilter to change the schema. code as below:
public class EnumSchemaFilter : ISchemaFilter
{
public void Apply(OpenApiSchema model, SchemaFilterContext context)
{
if (context.Type.IsEnum)
{
model.Enum.Clear();
Enum.GetNames(context.Type)
.ToList()
.ForEach(name => model.Enum.Add(new OpenApiString($"{Convert.ToInt64(Enum.Parse(context.Type, name))} = {name}")));
}
}
}
Configure the SwaggerGen to use above ShemaFilter.
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "ToDo API",
Description = "A simple example ASP.NET Core Web API",
TermsOfService = new Uri("https://example.com/terms"),
Contact = new OpenApiContact
{
Name = "Shayne Boyer",
Email = string.Empty,
Url = new Uri("https://twitter.com/spboyer"),
},
License = new OpenApiLicense
{
Name = "Use under LICX",
Url = new Uri("https://example.com/license"),
}
});
c.SchemaFilter<EnumSchemaFilter>();
});
The result like this:
I tried EnumSchemaFilter. I got some error every time i submited the request.
Because the serialize enum string to int
I used this code block and i hope it works
services.AddControllersWithViews()
.AddJsonOptions(
opts =>
{
var enumConverter = new JsonStringEnumConverter();
opts.JsonSerializerOptions.Converters.Add(enumConverter);
});

Aspnet core 3 -- How to return a text or csv file created as a string builder from a controller?

From a data table, I have generated a text file that I want to export as a .txt or .csv file using a controller action return. In aspx I was able to use:
MeetingListTxt = stringBuilder.ToString();
base.Response.Clear();
base.Response.AddHeader("content-disposition", "attachment;filename=MeetingList.csv");
base.Response.Charset = "";
base.Response.ContentType = "application/text";
base.Response.Output.Write(stringBuilder.ToString());
base.Response.Flush();
base.Response.End();
The result was a text file that the user could save to his hard drive.
How can this be done with Aspnet core 3?
As far as I know, in asp.net core we could use FileResult to generate the response which download the text file.
The FileResult will automatically provide the proper Content-Disposition header to attachment.
More details, you could refer to below test demo codes:
public class Student
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public IActionResult DownloadCommaSeperatedFile()
{
List<Student> students = new List<Student>
{
new Student { Id = 1, FirstName = "Joydip", LastName = "Kanjilal" },
new Student { Id = 2, FirstName = "Steve", LastName = "Smith" },
new Student { Id = 3, FirstName = "Anand", LastName = "Narayaswamy"}
};
try
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendLine("Id,FirstName,LastName");
foreach (var student in students)
{
stringBuilder.AppendLine($"{student.Id}, { student.FirstName},{ student.LastName}");
}
return File(Encoding.UTF8.GetBytes
(stringBuilder.ToString()), "text/csv", "student.csv");
}
catch
{
return Error();
}
}
Result:

Entity Framework Core OwnsOne unnecessary JOINS on same table

Entity framework core seems to create very complex queries when configuring value objects with OwnsOne on the same table.
Entity: Restaurant.cs
public class Restaurant : Entity, IAggregateRoot
{
public RestaurantId Id { get; private set; }
public string Name { get; private set; }
public Address Address { get; private set; }
protected Restaurant()
{
}
public Restaurant SetAddress(double lat, double lng, string street, string location, string zip, string country)
{
Address = new Address(lat, lng, street, location, zip, country);
return this;
}
}
Value object: Address.cs
public class Address : ValueObject
{
public Point Location { get; set; }
public string Street { get; private set; }
public string City { get; private set; }
public string Country { get; private set; }
public string Zip { get; private set; }
private Address() { }
public Address(double lat, double lng, string street, string city, string zip, string country)
{
Location = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326).CreatePoint(new Coordinate(lng, lat));
Street = street;
City = city;
Country = country;
Zip = zip;
}
protected override IEnumerable<object> GetAtomicValues()
{
yield return Street;
yield return City;
yield return Country;
yield return Zip;
}
}
EF Config: RestaurantEntityTypeConfig.cs
internal class RestaurantEntityTypeConfig : IEntityTypeConfiguration<Restaurant>
{
public void Configure(EntityTypeBuilder<Restaurant> builder)
{
builder.ToTable("Restaurant", SchemaNames.Restaurant);
builder.HasKey(c => c.Id);
builder.OwnsOne(c => c.Address, c=>
{
c.WithOwner();
});
}
}
Repository method:
public virtual async Task<T> FirstOrDefaultAsync(Expression<Func<T, bool>> predicate, params public virtual async Task<T> FirstOrDefaultAsync(Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] includeProperties)
{
var query = _dbContext.Set<T>().Where(predicate);
query = includeProperties.Aggregate(query, (current, includeProperty) => current.Include(includeProperty));
return await query.FirstOrDefaultAsync();
}
The query when selecting through repository looks like this:
SELECT TOP(1) [r].[Id], [r].[Name], [t].[Id], [t].[Address_City], [t].[Address_Country], [t].[Address_State], [t].[Address_Street], [t].[Address_ZipCode]
FROM [restaurant].[Restaurant] AS [r]
LEFT JOIN (
SELECT [r0].[Id], [r0].[Address_City], [r0].[Address_Country], [r0].[Address_State], [r0].[Address_Street], [r0].[Address_ZipCode], [r1].[Id] AS [Id0]
FROM [restaurant].[Restaurant] AS [r0]
INNER JOIN [restaurant].[Restaurant] AS [r1] ON [r0].[Id] = [r1].[Id]
WHERE [r0].[Address_ZipCode] IS NOT NULL OR ([r0].[Address_Street] IS NOT NULL OR ([r0].[Address_State] IS NOT NULL OR ([r0].[Address_Country] IS NOT NULL OR [r0].[Address_City] IS NOT NULL)))
) AS [t] ON [r].[Id] = [t].[Id]
WHERE [r].[Id] = #__p_0
The sql table looks like this:
My expected result would be a flat query since the value object is persisted to the same sql table. Is this a bug of entity framework or am I missing a configuration?

Assign permission for pages using Code first in asp.net MVC

Here I have created a Model Structure in asp.net mvc:
public class UserModel
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public List<Permission> Permissions { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Permission
{
public int PermissionID { get; set; }
public bool IsPermit { get; set; }
public string Name { get; set; }
}
and setting some default values in the list and while I am adding the user in the list I assign the permission for pages to that user through the UI (by checking permission checkboxes), so that user can access only the assigned pages:
public static class Repository
{
public static List<UserModel> GetUsers()
{
List<UserModel> listUsers = new List<UserModel>
{
new UserModel
{
UserId = 1,
UserName = "abc",
Password = "abc",
Permissions = new List<Permission>
{
new Permission
{
PermissionID = 1,
IsPermit = true,
Name = "Page1"
},
new Permission
{
PermissionID = 2,
IsPermit = false,
Name = "Page2"
},
new Permission
{
PermissionID = 3,
IsPermit = false,
Name = "Page3"
},
new Permission
{
PermissionID = 4,
IsPermit = false,
Name = "Page4"
}
},
FirstName = "Rohit",
LastName = "Sharma"
},
new UserModel
{
UserId = 2,
UserName = "xyz",
Password = "xyz",
Permissions = new List<Permission>
{
new Permission
{
PermissionID = 1,
IsPermit = false,
Name = "Page1"
},
new Permission
{
PermissionID = 2,
IsPermit = true,
Name = "Page2"
},
new Permission
{
PermissionID = 3,
IsPermit = true,
Name = "Page3"
},
new Permission
{
PermissionID = 4,
IsPermit = true,
Name = "Page4"
}
},
FirstName = "Rahul",
LastName = "Sharma"
}
};
return listUsers;
}
}
Now I want to do the same by using code first approach of database with the help of DbContext class. I have a static list of page permission in a database table (Id =1, Name=Page1; Id =2, Name=Page2; Id =3, Name=Page3; Id =4, Name=Page4).
I am confused while creating model structure for database. Please guide me how to create model structure and mapping of structure with the tables.
I have a table (Permission) in my database with default rows.
ID Name
1 Page1
2 Page2
3 Page3
4 Page4
Now, when I adding user I assigning permission to that user through static checkboxes (Page1, Page2, Page3 and Page4). That’s why I created static table in a database that contains list of pages. My User table is initially blank.
User
Id int NotNull
UserName nvarchar(100) AllowNull
Password nvarchar(100) AllowNull
FirstName nvarchar(100) AllowNull
LastName nvarchar(100) AllowNull
You can use below mentioned structure when you're using code first.You have to maintain conventions when you're using code first (But can be changed when you're using Fluent API).
Model Classes
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<Permission> Permissions { get; set; }
}
public class Permission
{
public int Id { get; set; }
public bool IsPermit { get; set; }
public string Name { get; set; }
public virtual User { get; set; }
}
Tables (This will auto generate.But If you want you can create manually also)
Users
Id int NotNull
UserName nvarchar(100) AllowNull
Password nvarchar(100) AllowNull
FirstName nvarchar(100) AllowNull
LastName nvarchar(100) AllowNull
Permissions
Id int NotNull
IsPermit bit AllowNull
Name nvarchar(100) AllowNull
User_Id int NotNull
DbContext Derived Class
public class UserEntities : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Permission> Permissions { get; set; }
}
Fore more information check Code-First Development with Entity Framework
I hope this will help to you.