Best practice to check duplicate string data before insert data using Entity Framework Core in C# - asp.net-core

I need an advice for my code. What I want to do is insert a row into a table using Entity Framework Core in ASP.NET Core.
Before inserting new data, I want to check if email and phone number is already used or not.
I want to return specifically, example if return = x, email used. If return = y, phone used.
Here's my code
public int Insert(Employee employee)
{
var checkEmail = context.Employees.Single(e => e.Email == employee.Email);
if (checkEmail != null)
{
var checkPhone = context.Employees.Single(e => e.Phone == employee.Phone);
if (checkPhone != null)
{
context.Employees.Add(employee);
context.SaveChanges();
return 1;
}
return 2;
}
return 3;
}
I'm not sure with my code, is there any advice for the best practice in my case?

I just don't like these "magic numbers" that indicate the result of your checks.... how are you or how is anyone else going to know what 1 or 2 means, 6 months down the road from now??
I would suggest to either at least create a constants class that make it's more obvious what these numbers mean:
public class CheckConstants
{
public const int Successful = 1;
public const int PhoneExists = 2;
public const int EmailExists = 3;
}
and then use these constants in your code:
public int Insert(Employee employee)
{
var checkEmail = context.Employees.Single(e => e.Email == employee.Email);
if (checkEmail != null)
{
var checkPhone = context.Employees.Single(e => e.Phone == employee.Phone);
if (checkPhone != null)
{
context.Employees.Add(employee);
context.SaveChanges();
return CheckConstants.Successful;
}
return CheckConstants.PhoneExists;
}
return CheckConstants.EmailExists;
}
and also in any code that calls this method and need to know about the return status code.
Alternatively, you could also change this to an enum (instead of an int):
public enum CheckConstants
{
Successful, PhoneExists, EmailExists
}
and then just return this enum - instead of an int - from your method:
public CheckConstants Insert(Employee employee)
{
var checkEmail = context.Employees.Single(e => e.Email == employee.Email);
if (checkEmail != null)
{
var checkPhone = context.Employees.Single(e => e.Phone == employee.Phone);
if (checkPhone != null)
{
context.Employees.Add(employee);
context.SaveChanges();
return CheckConstants.Successful;
}
return CheckConstants.PhoneExists;
}
return CheckConstants.EmailExists;
}

merge two database check to one Query
use SingleOrDefault instance of Single
public int Insert(Employee employee)
{
var checkEmail = context.Employees.Select (e=>new {e.Email , e.Phone }).SingleOrDefault(e => e.Email == employee.Email || e.Phone == employee.Phone);
if (checkEmail == null)
{
context.Employees.Add(employee);
context.SaveChanges();
return 1;
}
else if (checkEmail.Email == employee.Email)
return 3;
else
return 2;
}

Related

MVC Entity Framework, Query returns null

Hi guys can you help me understand why i keep getting a null instead of get the value.
Need to receive the saidaservicoid to be able to update. I receive the value from the view but can't update elemento. Stays null.
Thanks in advance for the help.
[Database]
[elementoRepository]
public async Task UpdateElementoSaidaServicosAsync(AddSaidasServicoViewModel model)
{
var saidaServico = await _context.SaidaServicos.FindAsync(model.SaidaServicoId);
var elemento = await _context.Elementos.FindAsync(model.ElementoId);
if (elemento == null)
{
return;
}
var updateElementoSaida = _context.Elementos.Where(e => e.Id == model.ElementoId).FirstOrDefault();
if (updateElementoSaida == null)
{
updateElementoSaida = new Elemento
{
saidaServico = saidaServico,
};
_context.Elementos.Update(updateElementoSaida);
}
else
{
int SaidaServicos = model.SaidaServicoId;
updateElementoSaida.saidaServico = saidaServico;
}
await _context.SaveChangesAsync();
return;
}
Ok. the best way that i found to solve this issue was to get the last ID.
int SaidaServicos = _context.SaidaServicos.Max(item => item.Id);

Conditional statement in getter method

Am relatively new to java so I have no idea what the problem is. In my getter settings of this class, I'm trying to evaluate if the input is of integer 1, 2 or 3, then it will return one of the previously saved setters described here. I used the same conditional statements in the setter, but the getter tells me that my method needs to return type int. What am I doing wrong? Or should I be doing this a completely different way? lol.
public class AssignmentMarks {
private String courseName;
private int assignment1 = 0, assignment2 = 0, assignment3 = 0;
public AssignmentMarks(String name, int mark1, int mark2, int mark3){
//create constructor to use variables.
this.courseName = name;
this.assignment1 = mark1;
this.assignment2 = mark2;
this.assignment3 = mark3;
}
public void setMark(int assignmentNumber, int mark) {
//assign value of the assignments
if(assignmentNumber == 1) {
mark = this.assignment1;
}else if(assignmentNumber == 2) {
mark = this.assignment2;
}else if(assignmentNumber == 3){
mark = this.assignment3;
}
}
public int getMark(int assignmentNum) {
if(assignmentNum == 1) {
return assignment1;
}else if (assignmentNum == 2) {
return assignment2;
} else if (assignmentNum == 3) {
return assignment3;
}
}
}
public int getMark(int assignmentNum) {
if(assignmentNum == 1) {
return assignment1;
}else if (assignmentNum == 2) {
return assignment2;
} else if (assignmentNum == 3) {
return assignment3;
}
// in another case
throw new Exception("Assignment must be 1, 2 or 3);
}
for setter
public void setMark(int assignmentNumber, int mark) {
//assign value of the assignments
if(assignmentNumber == 1) {
// BAD mark = this.assignment1; don't set parameter is useless
this.assignment1=mark;
}else if(assignmentNumber == 2) {
// BAD mark = this.assignment2;
this.assignment2=mark;
}else if(assignmentNumber == 3){
// BAD mark = this.assignment3;
this.assignment3=mark;
}
// in another case
throw new Exception("Assignment must be 1, 2 or 3");
}
I don't remember if you must import Exception for throwing them.
if yes put import java.lang.Exception on top of your code.
your logic can be improved using arrays, but let's walk, and after you will running...

How to create url with complex query

I use dart and flutter for mobile app. I use my api to get data from server. But I found a problem, maybe its dart core problem.
I need to add complex queryParams to my URL like
Map<String, Map<String, List<String>>>{"a": {"b": ["c","d"]}, "e": {}}
I use Uri.parse(url).replace(queryParams: myQueryParams).toString()
But Uri.replace() accepts only Map<String, Iterable<String>> and throws an error
Unhandled Exception: type '_InternalLinkedHashMap<String, List<String>>' is not a subtype of type 'Iterable<dynamic>'
I found method which throws this error
static String _makeQuery(String query, int start, int end,
Map<String, dynamic /*String|Iterable<String>*/ > queryParameters) {
if (query != null) {
if (queryParameters != null) {
throw ArgumentError('Both query and queryParameters specified');
}
return _normalizeOrSubstring(query, start, end, _queryCharTable,
escapeDelimiters: true);
}
if (queryParameters == null) return null;
var result = StringBuffer();
var separator = "";
void writeParameter(String key, String value) {
result.write(separator);
separator = "&";
result.write(Uri.encodeQueryComponent(key));
if (value != null && value.isNotEmpty) {
result.write("=");
result.write(Uri.encodeQueryComponent(value));
}
}
queryParameters.forEach((key, value) {
if (value == null || value is String) {
writeParameter(key, value);
} else {
Iterable values = value;
for (String value in values) {
writeParameter(key, value);
}
}
});
return result.toString();
}
So my question is there is some method in dart to add my queryParams to url or I need to create it by my own?
I have modified original method and now its work.
class UrlCreator {
static String addQueryParams(String url, Map<String, dynamic> queryParams) {
var result = StringBuffer();
var separator = "";
void writeParameter(String key, String value) {
result.write(separator);
separator = "&";
result.write(Uri.encodeQueryComponent(key));
if (value != null && value.isNotEmpty) {
result.write("=");
result.write(Uri.encodeQueryComponent(value));
}
}
void buildQuery(Map queryParams, {parentKey}){
queryParams.forEach((key, value){
print("parentKey = $parentKey Key = $key value = $value");
if (value == null || value is String) {
var newKey = parentKey != null ? "$parentKey[$key]" : key;
writeParameter(newKey, value);
} else if (value is Map) {
buildQuery(value, parentKey: key);
} else {
Iterable values = value;
var newKey = parentKey != null ? "$parentKey[$key][]" : "$key[]";
for (String value in values) {
writeParameter(newKey, value);
}
}
});
}
buildQuery(queryParams);
return url + "?" + result.toString();
}
}

Throwing an Exception In an Xss Attack

This is a Web API which Json payloads (so, no Razor).
I'm using ASP.NET Core 2.1
1st up I should mention that I am sanitizing the relevant inputs with HtmlEncoder. However, that is just in case any gets past my validator, which I want to ask about here.
I want to write a validator which will return an error code where a user tries to include an html string in an input (using a mobile app, which would be a property in the json payload).
I've seen some naive implementation suggestion here on SO - usually just checking to see of the string contains '<' or '>' (and maybe one or 2 other chars).
I guess I would like to know if that is sufficient for the task at hand. There's no reason for a user to post any kind of html/xml in this domain.
A lot of the libraries around will sanitize input. But none of them seem to have a method which tells you if a string contains potentially harmful input.
As I said, I'm already sanitizing (as a last line of defence). But ideally I would return an error code before it gets to that.
Use this class from Microsoft ASP.NET Core 1
// <copyright file="CrossSiteScriptingValidation.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
public static class CrossSiteScriptingValidation
{
private static readonly char[] StartingChars = { '<', '&' };
#region Public methods
// Only accepts http: and https: protocols, and protocolless urls.
// Used by web parts to validate import and editor input on Url properties.
// Review: is there a way to escape colon that will still be recognized by IE?
// %3a does not work with IE.
public static bool IsDangerousUrl(string s)
{
if (string.IsNullOrEmpty(s))
{
return false;
}
// Trim the string inside this method, since a Url starting with whitespace
// is not necessarily dangerous. This saves the caller from having to pre-trim
// the argument as well.
s = s.Trim();
var len = s.Length;
if ((len > 4) &&
((s[0] == 'h') || (s[0] == 'H')) &&
((s[1] == 't') || (s[1] == 'T')) &&
((s[2] == 't') || (s[2] == 'T')) &&
((s[3] == 'p') || (s[3] == 'P')))
{
if ((s[4] == ':') || ((len > 5) && ((s[4] == 's') || (s[4] == 'S')) && (s[5] == ':')))
{
return false;
}
}
var colonPosition = s.IndexOf(':');
return colonPosition != -1;
}
public static bool IsValidJavascriptId(string id)
{
return (string.IsNullOrEmpty(id) || System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(id));
}
public static bool IsDangerousString(string s, out int matchIndex)
{
//bool inComment = false;
matchIndex = 0;
for (var i = 0; ;)
{
// Look for the start of one of our patterns
var n = s.IndexOfAny(StartingChars, i);
// If not found, the string is safe
if (n < 0) return false;
// If it's the last char, it's safe
if (n == s.Length - 1) return false;
matchIndex = n;
switch (s[n])
{
case '<':
// If the < is followed by a letter or '!', it's unsafe (looks like a tag or HTML comment)
if (IsAtoZ(s[n + 1]) || s[n + 1] == '!' || s[n + 1] == '/' || s[n + 1] == '?') return true;
break;
case '&':
// If the & is followed by a #, it's unsafe (e.g. S)
if (s[n + 1] == '#') return true;
break;
}
// Continue searching
i = n + 1;
}
}
#endregion
#region Private methods
private static bool IsAtoZ(char c)
{
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
#endregion
}
Then use this middleware to control URL,Query Parameteres and Content:
public class XssMiddleware
{
private readonly RequestDelegate _next;
public XssMiddleware(RequestDelegate next)
{
if (next == null)
{
throw new ArgumentNullException(nameof(next));
}
_next = next;
}
public async Task Invoke(HttpContext context)
{
// Check XSS in URL
if (!string.IsNullOrWhiteSpace(context.Request.Path.Value))
{
var url = context.Request.Path.Value;
int matchIndex;
if (CrossSiteScriptingValidation.IsDangerousString(url, out matchIndex))
{
throw new CrossSiteScriptingException("YOUR_ERROR_MESSAGE");
}
}
// Check XSS in query string
if (!string.IsNullOrWhiteSpace(context.Request.QueryString.Value))
{
var queryString = WebUtility.UrlDecode(context.Request.QueryString.Value);
int matchIndex;
if (CrossSiteScriptingValidation.IsDangerousString(queryString, out matchIndex))
{
throw new CrossSiteScriptingException("YOUR_ERROR_MESSAGE");
}
}
// Check XSS in request content
var originalBody = context.Request.Body;
try
{
var content = await ReadRequestBody(context);
int matchIndex;
if (CrossSiteScriptingValidation.IsDangerousString(content, out matchIndex))
{
throw new CrossSiteScriptingException("YOUR_ERROR_MESSAGE");
}
await _next(context);
}
finally
{
context.Request.Body = originalBody;
}
}
private static async Task<string> ReadRequestBody(HttpContext context)
{
var buffer = new MemoryStream();
await context.Request.Body.CopyToAsync(buffer);
context.Request.Body = buffer;
buffer.Position = 0;
var encoding = Encoding.UTF8;
var contentType = context.Request.GetTypedHeaders().ContentType;
if (contentType?.Charset != null) encoding = Encoding.GetEncoding(contentType.Charset);
var requestContent = await new StreamReader(buffer, encoding).ReadToEndAsync();
context.Request.Body.Position = 0;
return requestContent;
}
}

createUrl doesn't work correctly within extended CBaseUrlRule class

I made my own class that extends CBaseUrlRule to manage some sort of pages on site. Result class code is
class HotelUrlRule extends CBaseUrlRule {
public function parseUrl($manager,$request,$pathInfo,$rawPathInfo) {
if(isset($_GET['id'])) {
if (($_GET['id'] != 0) && ($pathInfo == 'hotel')) {
return 'hotel/index';
}
}
return false;
}
public function createUrl($manager,$route,$params,$ampersand) {
if ($route == 'hotel/index') {
Yii::import('application.controllers.SearchController');
$searcher = new SearchController($this, NULL);
$hotelRaw = $searcher->actionGetHotelInformation($_GET['id']);
$hotelRaw = $hotelRaw['GetHotelInformationResult'];
$hotelName = $hotelRaw['Name'];
$hotelName = preg_replace('%(\s)%', '-', $hotelName);
return 'hotel/' . $hotelName;
}
return false;
}
}
The condition in parseUrl ($_GET['id'] != 0) && ($pathInfo == 'hotel') returns 'true' and the condition in createUrl ($route == 'hotel/index') returns 'false'. Var_dump of $route is 'admin/auth'.
Why is it so? Any guesses?