How can i get the keys and errors from the ModelStateDictionary? I have this piece of code, but it's done too many times and it throws me a duplicate key error.
if (!modelstate.IsValid)
{
var errMessages = new Dictionary<string, string>();
foreach (var item in modelstate.Keys)
{
foreach (var item2 in modelstate.Values)
{
foreach (var item3 in item2.Errors)
{
errMessages.Add(item.ToLower(), item3.ErrorMessage);
}
}
}
return new Error { StatusCode = 409, ErrorMessages = errMessages };
}
Thanks for all answers, have a nice day :D.
I managed to solve this problem, but if someone has better suggestions, I would like to read it.
if (!modelstate.IsValid)
{
var errMessages = new Dictionary<string, string>();
var i = 0;
foreach (var item2 in modelstate.Values.SelectMany(p => p.Errors))
{
var key = modelstate.Keys.ToArray();
errMessages.Add(key[i].ToLower(), item2.ErrorMessage);
i++;
}
return new Error { StatusCode = 409, ErrorMessages = errMessages };
}
Related
I am onboarding alone on an existing project that do not have any unit test. My first goal before any refactoring is to cover 100% of the code. I would like to avoid any regression.
I have read how do I mock sqlconnection or should I refactor the code? but my case as you can see below is quite different cause I need to do more than stub simply the sqlConnection. Basically, I need to mock the db. I would like to know the best approach to achieve it.
(By the way, I do not want to use any ORM such as Entity).
Below the code of the repository :
public class HotelRepository : IHotelRepository
{
private readonly IDbConnection _dbConnection;
private readonly ILogService _loggerService;
public HotelRepository(IDbConnection dbConnection, ILogService loggerService)
{
_dbConnection = dbConnection;
_loggerService = loggerService;
}
public HotelDo GetByRid(string rid)
{
return Find(rid).FirstOrDefault();
}
public List<HotelDo> Find(string text)
{
try
{
_dbConnection.Open();
var items = new List<HotelDo>();
using (var command = _dbConnection.CreateCommand())
{
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "dbo.HotelSearchByRidOrName";
command.Parameters.Add(new SqlParameter("#Text", text));
using (var reader = command.ExecuteReader(CommandBehavior.CloseConnection))
{
while (reader.Read())
{
items.Add(new HotelDo()
{
Name = SqlExtension.ReaderToStringConverter(reader["Name"]),
Id = SqlExtension.ReaderToIntConverter(reader["Id"]),
Rid = SqlExtension.ReaderToStringConverter(reader["RIDHotel"]),
IdPms = SqlExtension.ReaderToNullableIntConverter(reader["IdPms"]),
LinkResaWeb = SqlExtension.ReaderToStringConverter(reader["LinkResaWeb"]),
LinkPms = SqlExtension.ReaderToStringConverter(reader["LinkPms"]),
IdBrand = SqlExtension.ReaderToNullableIntConverter(reader["IdBrand"]) ?? 0,
IsOnline = SqlExtension.ReaderToBoolConverter(reader["IsOnline"]) ?? false,
CodeCountry = SqlExtension.ReaderToStringConverter(reader["CodeCountry"])
});
}
}
}
return items;
}
catch (Exception e)
{
var errorMessage = $"HotelRepository Find, text {text} ";
_loggerService.Trace(LogSeverity.Error, errorMessage, e);
throw new DalException() { Source = errorMessage, };
}
finally
{
_dbConnection.Close();
}
}
public List<HotelDo> GetAll()
{
try
{
_dbConnection.Open();
var items = new List<HotelDo>();
using (var command = _dbConnection.CreateCommand())
{
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "dbo.HotelGetAll";
using (var reader = command.ExecuteReader(CommandBehavior.CloseConnection))
{
while (reader.Read())
{
bool.TryParse(reader["IsOnline"].ToString(), out var isOnline);
items.Add(new HotelDo()
{
Id = SqlExtension.ReaderToIntConverter(reader["Id"]),
Rid = SqlExtension.ReaderToStringConverter(reader["RIDHotel"]),
Name = SqlExtension.ReaderToStringConverter(reader["Name"]),
CodeCountry = SqlExtension.ReaderToStringConverter(reader["CodeCountry"]),
LinkPms = SqlExtension.ReaderToStringConverter(reader["LinkPms"]),
IdPms = SqlExtension.ReaderToNullableIntConverter(reader["IdPms"]),
IdBrand = SqlExtension.ReaderToNullableIntConverter(reader["IdBrand"]) ?? 0,
LinkResaWeb = SqlExtension.ReaderToStringConverter(reader["LinkResaWeb"]),
IsOnline = isOnline
});
}
}
}
return items;
}
catch (Exception e)
{
var errorMessage = $"HotelRepository GetAllHotels";
_loggerService.Trace(LogSeverity.Error, errorMessage, e);
throw new DalException() { Source = errorMessage, };
}
finally
{
_dbConnection.Close();
}
}
}
Thank you for your help
So based on what you've got I've set up a test frame for you to follow. I've removed less important components for breviety.
Before you you jump in I just want to give my 2 cents, if you don't know how to do this sort of thing you seem to be more or less in a junior position or less experiance with C# and also found your self in a more or less mature company that doesn't care about the development deparment, since an uncovered project just get's thrown your way says you don't have alot of resources to go about to imrpove the code base.
Test only the things that have business value (can you put a price on the piece of logic if it brakes)
Delivering stuff faster will make you look better as a programmer (noone in the business gives a damn about test covarage)
Study hard, get your experiance, good reputation and don't be afraid to get the hell out of there as soon as you start getting bored.
Main
void Main()
{
var idIndex = 0;
var ids = new string[] { "1", "2" };
var mockDataReader = new Mock<IDataReader>();
mockDataReader.SetupSequence(x => x.Read()).Returns(true).Returns(true).Returns(false);
mockDataReader.SetupGet(x => x["Id"]).Returns(() => ids[idIndex]).Callback(() => idIndex++);
var mockParameters = new Mock<IDataParameterCollection>();
var mockCommand = new Mock<IDbCommand>();
mockCommand.SetupGet(x => x.Parameters).Returns(mockParameters.Object);
mockCommand.Setup(x => x.ExecuteReader(CommandBehavior.CloseConnection)).Returns(mockDataReader.Object);
var mockConnection = new Mock<IDbConnection>();
mockConnection.Setup(x => x.CreateCommand()).Returns(mockCommand.Object);
var repo = new HotelRepository(mockConnection.Object);
var result = repo.Find("search");
Assert.Equal("1", result[0].Id);
Assert.Equal("2", result[1].Id);
}
Repository
public class HotelRepository
{
private readonly IDbConnection _dbConnection;
public HotelRepository(IDbConnection dbConnection)
{
_dbConnection = dbConnection;
}
public List<Pony> Find(string text)
{
_dbConnection.Open();
var items = new List<Pony>();
using (var command = _dbConnection.CreateCommand())
{
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "dbo.HotelSearchByRidOrName";
command.Parameters.Add(new SqlParameter("#Text", text));
using (var reader = command.ExecuteReader(CommandBehavior.CloseConnection))
{
while (reader.Read())
{
items.Add(new Pony
{
Id = reader["Id"].ToString()
});
}
}
}
return items;
}
}
Just a dumb o'l pony
public class Pony {
public string Id { get; set; }
}
I am new to .netcore mvc architecture. I am trying to consume the api data response, So far I have successfully fetched the data, but the problem I am facing is when the api response/result is more than one. Forexample if the actuall api response is the following
"responseHeader":{
"status":0,
"QTime":0,
"params":{
"q":"title:\"A\""}},
"response":{"numFound":3,"start":0,"docs":[
{
"date":"1970-01-01T00:00:00Z",
"tstamp":"2019-11-22T12:22:31.698Z",
"digest":"e23d679991d80d832504e7395d139fe4",
"contentLength":"25476",
"boost":0.0,
"title":["emb- A1]
"url":"https://www.example.com/a/b/c0/"},
{
"date":"1970-01-01T00:00:00Z",
"tstamp":"2019-11-22T12:22:31.698Z",
"digest":"e23d679991d80d832504e7395d139fe4",
"contentLength":"25476",
"boost":0.0,
"title":["emb - A2]
"url":"https://www.example.com/a/b/c1/"
},
{
"date":"1970-01-01T00:00:00Z",
"tstamp":"2019-11-22T12:22:31.698Z",
"digest":"e23d679991d80d832504e7395d139fe4",
"contentLength":"25476",
"boost":0.0,
"title":["emb - A3]
"url":"https://www.example.com/a/b/c2/"
}
I am only getting
{"title":"[\r\n \"emb- A1","source":"https://www.example.com/a/b/c0/"}
instead of having all the response data.
My Code is below.
Model
SearchModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace searchEngineTesting.Models
{
public class SearchModel
{
public string Title;
public string Source;
}
}
Controller
EngineController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using searchEngineTesting.Models;
namespace searchEngineTesting.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class EngineController : ControllerBase {
[HttpGet("[action]/{query}")]
public async Task<IActionResult> Product(string query)
{
var model = new SearchModel();
using (var client = new HttpClient())
{
try
{
client.BaseAddress = new Uri("http://xx.xx.xxx.xx:8080");
var response = await client.GetAsync($"/abc/xxx/select?q=title%3A%22{query}%22");
response.EnsureSuccessStatusCode();
var stringResult = await response.Content.ReadAsStringAsync();
var root = (JObject)JsonConvert.DeserializeObject(stringResult);
//var details = JsonConvert.DeserializeObject<SearchModel>(stringResult);
var items = root.SelectToken("").Children().OfType<JProperty>().ToDictionary(p => p.Name, p => p.Value);
foreach (var item in items)
{
if (item.Key == "response")
{
var key = item.Value.SelectToken("").OfType<JProperty>().ToDictionary(p => p.Name, p => p.Value);
foreach (var k in key)
{
if(k.Key == "docs")
{
var tests = JsonConvert.DeserializeObject<JArray>(k.Value.ToString());
var data = k.Value.SelectToken("").Children().First();
var test = data.SelectToken("").Children().OfType<JProperty>().ToDictionary(p => p.Name, p => p.Value).ToList();
foreach (var t in test)
{
if (t.Key =="url")
{
model.Source = t.Value.ToString();
}
else if (t.Key == "title")
{
model.Title = t.Value.ToString(); }
}
}
}
}
}
return new JsonResult(model);
}
catch (InvalidOperationException httpreq) {
return BadRequest("Sorry: There are no results for your query");
}
}
}
}
}
How can I retrieve whole of the response I am getting from actual API.
Please help..!
How can I retrieve whole of the response I am getting from actual API.
If you want to return all the actual api response,then just use below code:
[HttpGet("[action]/{query}")]
public async Task<IActionResult> Product(string query)
{
var model = new SearchModel();
using (var client = new HttpClient())
{
try
{
client.BaseAddress = new Uri("http://xx.xx.xxx.xx:8080");
var response = await client.GetAsync($"/abc/xxx/select?q=title%3A%22{query}%22");
response.EnsureSuccessStatusCode();
var stringResult = await response.Content.ReadAsStringAsync();
var root = (JObject)JsonConvert.DeserializeObject(stringResult);
return new JsonResult(root);
}
catch (InvalidOperationException httpreq)
{
}
}
return Ok()
}
If you would like to just return List<SearchModel> from the actual response,you should not use var data = k.Value.SelectToken("").Children().First(); which will only retrieve the first element of docs array.
Try to foreach k.Value.SelectToken("").Children() and return List<SearchModel> instead of a SearchModel,refer to
[HttpGet("[action]/{query}")]
public async Task<IActionResult> Product(string query)
{
//initialize a list SearchModel
var modelList = new List<SearchModel>();
using (var client = new HttpClient())
{
try
{
client.BaseAddress = new Uri("http://xx.xx.xxx.xx:8080");
var response = await client.GetAsync($"/abc/xxx/select?q=title%3A%22{query}%22");
response.EnsureSuccessStatusCode();
var stringResult = await response.Content.ReadAsStringAsync();
var root = (JObject)JsonConvert.DeserializeObject(stringResult);
var items = root.SelectToken("").Children().OfType<JProperty>().ToDictionary(p => p.Name, p => p.Value);
foreach (var item in items)
{
if (item.Key == "response")
{
var key = item.Value.SelectToken("").OfType<JProperty>().ToDictionary(p => p.Name, p => p.Value);
foreach (var k in key)
{
if (k.Key == "docs")
{
//remove .First()
var arrayData = k.Value.SelectToken("").Children();
foreach(var data in arrayData)
{
var model = new SearchModel();
var test = data.SelectToken("").Children().OfType<JProperty>().ToDictionary(p => p.Name, p => p.Value).ToList();
foreach (var t in test)
{
if (t.Key == "url")
{
model.Source = t.Value.ToString();
}
else if (t.Key == "title")
{
model.Title = t.Value.ToString();
}
}
modelList.Add(model);
}
}
}
}
}
return new JsonResult(modelList);
}
catch (InvalidOperationException httpreq)
{
}
}
return Ok();
}
Your model is not a list, but only a single object which you would overwrite continuously in your loop so that only one element remains.
Then you will need to iterate over all docs, not just use the first (e.g. k.Value.SelectToken("").Children().First()).
So you should be able to resolve your issue by changing your model to a List of SearchModels, and ensuring to iterate through all documents (it helps to inspect the variables in a debugger to see what happens).
An easier approach would be using JsonConvert, where you just would need to mirror the relevant structure of the JSON using C# classes, e.g.:
public class Document
{
public string Title;
public string Url;
}
public class Result
{
public Response response;
}
public class Response
{
public List<Document> docs;
}
then deserialize the json simple as:
var result = JsonConvert.DeserializeObject<Result>(stringResult);
and finally converting the result to your SearchModel:
var searchModels = result.response.docs.Select(x => new SearchModel {Source = x.Url, Title = x.Title}).ToList();
help me, i couldn't get the cookies from an httprequest, i tried the plugins.settings, i tried the pcl share too, am in this problem for a month
public async Task<bool> PostAsync(AuthUser user)
{
var CookieContainer = new CookieContainer();
var handler = new HttpClientHandler() { CookieContainer =
CookieContainer };
var _client = new HttpClient(handler);
IEnumerable<string> cookieStrings = null;
//var httpClient = new HttpClient();
_client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
var json = JsonConvert.SerializeObject(user);
HttpContent httpContent = new StringContent(json);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
try
{
string url = WebServiceUrl + "j_spring_security_check?j_username=" + user.j_username +"&j_password=" + user.j_password + "&ajax=true";
HttpResponseMessage result = await _client.PostAsync(url, httpContent);
IEnumerable<string> cookies;
if (result.Headers.TryGetValues("set-cookie", out cookies))
{
foreach (var c in cookies)
{
await App.Current.MainPage.DisplayAlert("Cookie", c , "OK");
}
}
if (result.IsSuccessStatusCode)
{
using (var responsecontent = result.Content)
{
string resultString = responsecontent.ReadAsStringAsync().Result;
var response = JsonConvert.DeserializeObject<AuthUser>(resultString);
if (response.error != null)
{
await App.Current.MainPage.DisplayAlert("Error", response.result.error, "OK");
return false;
}
else if (response.result.success.Equals("1"))
{
App.Current.MainPage = new NavigationPage(new TimelineMenuPage(response.result.user_id.ToString(), response.result.token));
return true;
}
}
}
return result.IsSuccessStatusCode;
}
catch (Exception e)
{
await App.Current.MainPage.DisplayAlert("Alert", e.ToString(), "OK");
throw;
}
}
when debugging it skips this part :
if (result.Headers.TryGetValues("set-cookie", out cookies))
{
foreach (var c in cookies)
{
await App.Current.MainPage.DisplayAlert("Cookie", c , "OK");
}
}
**and then i get in CookieContainer count=0 **
Since you are already using a CookieContainer, and you will know the Uri you are getting them from, why don't you just get the Cookies directly from the Container, instead of a set-cookie command, that you will then have to parse.
cookieContainer.GetCookies(new Uri("mydomain.com"));
After your HttpRequest, it will automatically put them into the CookieContainer.
I always have reduce issue on practicing, like following map and reduce, if I add more document or add more field to emit in the map and reduce like following. it will return values as [], not sure what occur this?
problemNumber : doc.problemNumber,
UserId: idv,
event : doc.event
......
Map
function(doc) {
if(doc.event){
var idv = null;
for (var idu in doc.Data.users){
if (doc.eventData.users[idu].userTypeCode == "M"){
idv = doc.Data.users[idu].UserId;
}
}
var newDoc = {
problemNumber : doc.problemNumber,
UserId: idv,
event : doc.event
};
emit(null, newDoc);
}
}
Reduce
function(keys, values, rereduce) {
var result = [];
var closeMap = {};
for (var i=0; i<values.length; i++){
var doc = values[i];
if (doc.event=='CLOSE'){
closeMap[doc.problemNumber] = 1;
}
}
for (var i=0; i<values.length; i++){
var doc = values[i];
if (doc.event=='OPEN'){
if (closeMap[doc.problemNumber]){
doc.event = 'CLOSE';
}
result.push(doc);
}
}
return result;
}
I've been receiving an error from Amazon web service - InvalidParameterValue
Either Action or Operation query parameter must be present.
I believe it is most likely due to the signature being incorrect as the XML document and Header matches that of a test I did in their scratchpad.
Does anything stand out as being incorrect?
Thanks,
Clare
private static string ConstructCanonicalQueryString(SortedDictionary<string, string> sortedParameters)
{
var builder = new StringBuilder();
if (sortedParameters.Count == 0)
{
builder.Append(string.Empty);
return builder.ToString();
}
foreach (var kvp in sortedParameters)
{
builder.Append(PercentEncodeRfc3986(kvp.Key));
builder.Append("=");
builder.Append(PercentEncodeRfc3986(kvp.Value));
builder.Append("&");
}
var canonicalString = builder.ToString();
return canonicalString.Substring(0, canonicalString.Length - 1);
}
private static string PercentEncodeRfc3986(string value)
{
value = HttpUtility.UrlEncode(string.IsNullOrEmpty(value) ? string.Empty : value, Encoding.UTF8);
if (string.IsNullOrEmpty(value))
{
return string.Empty;
}
value = value.Replace("'", "%27")
.Replace("(", "%28")
.Replace(")", "%29")
.Replace("*", "%2A")
.Replace("!", "%21")
.Replace("%7e", "~")
.Replace("+", "%20")
.Replace(":", "%3A");
var sbuilder = new StringBuilder(value);
for (var i = 0; i < sbuilder.Length; i++)
{
if (sbuilder[i] != '%')
{
continue;
}
if (!char.IsLetter(sbuilder[i + 1]) && !char.IsLetter(sbuilder[i + 2]))
{
continue;
}
sbuilder[i + 1] = char.ToUpper(sbuilder[i + 1]);
sbuilder[i + 2] = char.ToUpper(sbuilder[i + 2]);
}
return sbuilder.ToString();
}
public string SignRequest(Dictionary<string, string> parametersUrl, Dictionary<string, string>
parametersSignture)
{
var secret = Encoding.UTF8.GetBytes(parametersSignture["Secret"]);
var signer = new HMACSHA256(secret);
var pc = new ParamComparer();
var sortedParameters = new SortedDictionary<string, string>(parametersUrl, pc);
var orderedParameters = ConstructCanonicalQueryString(sortedParameters);
var builder = new StringBuilder();
builder.Append(parametersSignture["RequestMethod"])
.Append(" \n")
.Append(parametersSignture["EndPoint"])
.Append("\n")
.Append("/\n")
.Append(orderedParameters);
var stringToSign = builder.ToString();
var toSign = Encoding.UTF8.GetBytes(stringToSign);
var sigBytes = signer.ComputeHash(toSign);
var signature = Convert.ToBase64String(sigBytes);
return signature.Replace("=", "%3D").Replace("/", "%2F").Replace("+", "%2B");
}
public class ParamComparer : IComparer<string>
{
public int Compare(string p1, string p2)
{
return string.CompareOrdinal(p1, p2);
}
}
The issue was that the Action wasn't included correctly into the Request