I have encountered a problem when trying to call my web api with a post request, a empty array is returned.
My method is:
// POST: Api/v1/transaction/
[HttpPost]
public HttpResponseMessage Post(string user)
{
var userId = new Guid(user);
var transactions = new Collection<TransactionDataTransferObject>();
try
{
var seller = _databaseContext.Sellers.Single(s => s.Id == userId);
var sellerMedias = _databaseContext.Medias.Where(m => m.TakenBy.Id == seller.Id);
foreach (var sellerMedia in sellerMedias)
{
var allLogsForMedia = _databaseContext.Logs.Where(l => l.ObjectReferenceId == sellerMedia.Id);
foreach (var logMedia in allLogsForMedia)
{
var transaction = new TransactionDataTransferObject
{
Date = logMedia.DateTimeInUtc,
Amount = sellerMedia.PriceInSek,
MediaName = sellerMedia.FileName,
UserName = seller.FirstName + " " + seller.LastName
};
transactions.Add(transaction);
}
}
}
catch (Exception exception)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, exception);
}
return Request.CreateResponse(HttpStatusCode.OK, transactions);
}
When I debug transactions variable, I see two objects in the collection.
My response to postman is
[
{},
{}
]
What have I done wrong? Where is my data which is sent?
Ok, after some hours of slaming my head in the table i found out that I used
[DataContract] as filter on the ViewModel,TransactionDataTransferObject.
Like this:
[DataContract]
public class TransactionDataTransferObject
{
[Display(Name = "Date")]
public DateTime Date { get; set; }
public string MediaName { get; set; }
public Guid MediaId { get; set; }
public string UserName { get; set; }
public Guid UserId { get; set; }
[Display(Name = "Description")]
public string Discriminator { get; set; }
[Display(Name = "Amount")]
public decimal Amount { get; set; }
}
Which was wrong in this case...
Thanks for reading!
Related
I want custom object in response of API having [required] data annotation on model properties like this:
{
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "fatal",
"code": "required",
"location": [
"/f:AllergyIntolerance/f:status"
]
}
]
}
Is it possible to do it or I would have to code it.
Because model validation happens before action is called, is there any way I can do it?
To create custom request and respond samples for your api, you can use Swashbuckle.AspNetCore.Swagger and to improve validations on your models you can use FluentValidations Sample. Good Luck!
first for simplify define your models like these :
public class ResponseModel
{
public string resourceType { get; set; }
public List<ResponseIssueModel> issue { get; set; } = new List<ResponseIssueModel>();
}
public class ResponseIssueModel
{
public string severity { get; set; }
public string code { get; set; }
public List<string> locations { get; set; } = new List<string>();
}
Then on your actions you can return this :
var response = new ResponseModel();
response.resourceType = "OperationOutcome";
response.issue.Add(new ResponseIssueModel
{
severity = "fatal",
code = "required",
locations = { "/f:AllergyIntolerance/f:status" }
});
return Ok(response);
you can use Builder Pattern for easy create response object
If you want to validate your model in controller,you could try with TryValidateModel method as mentioned in the document:
I tried as below:
in controller:
var model = new TestModel() { Id=1,nestedModels=new List<NestedModel>() { new NestedModel() { Prop1="P11"} } };
var isvalid=TryValidateModel(model);
var errorfiledlist = new List<string>();
if (!isvalid)
{
foreach (var value in ModelState.Values)
{
foreach (var error in value.Errors)
{
errorfiledlist.Add(MidStrEx(error.ErrorMessage,"The "," field"));
}
}
}
var jsonstring = JsonSerializer.Serialize(model);
foreach (var field in errorfiledlist)
{
var oldstr = String.Format("\"{0}\":null", field);
var newstr = String.Format("\"{0}\":\"required\"", field);
jsonstring = jsonstring.Replace(oldstr, newstr);
};
var obj = JsonSerializer.Deserialize<Object>(jsonstring);
return Ok(obj);
MidStrEx method:
public static string MidStrEx(string sourse, string startstr, string endstr)
{
string result = string.Empty;
int startindex, endindex;
try
{
startindex = sourse.IndexOf(startstr);
if (startindex == -1)
return result;
string tmpstr = sourse.Substring(startindex + startstr.Length);
endindex = tmpstr.IndexOf(endstr);
if (endindex == -1)
return result;
result = tmpstr.Remove(endindex);
}
catch (Exception ex)
{
}
return result;
}
Models:
public class TestModel
{
public int Id { get; set; }
[Required]
public string Prop { get; set; }
public List<NestedModel> nestedModels { get; set; }=new List<NestedModel>();
}
public class NestedModel
{
public string Prop1 { get; set; }
[Required]
public string Prop2 { get; set; }
}
The result:
In my ASP.NET Core 6 Web API using Entity Framework, I am working on an Employee Leave Application.
And I have this model class:
public class EmployeeLeave
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
public virtual Employee Employee { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public LeaveType LeaveType { get; set; }
public bool? IsCurrent { get; set; }
}
Then I also created some DTO as shown here:
public class LeaveRequestDto
{
public Guid EmployeeId { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public LeaveType LeaveType { get; set; }
}
public class LeaveResponseDto
{
public EmployeeResponseDto Employee { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public string LeaveType { get; set; }
public bool? IsCurrent { get; set; }
}
Then I have the service for the implementation.
Interface:
Task<GenericResponseDto<LeaveResponseDto>> CreateAsync(LeaveRequestDto request);
Implementation:
public async Task<GenericResponseDto<LeaveResponseDto>> CreateAsync(LeaveRequestDto request)
{
var response = new GenericResponseDto<LeaveResponseDto>();
var employee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == request.EmployeeId);
if (employee == null)
{
response.Error = new ErrorResponseDto()
{
ErrorCode = 404,
Message = "Employee does not exist in the system!"
};
response.StatusCode = 404;
}
else
{
var leave = _mapper.Map<EmployeeLeave>(request);
leave.Employee = employee;
leave.IsCurrent = true;
try
{
_context.EmployeeLeaves.Add(leave);
await _context.SaveChangesAsync();
response.Result = _mapper.Map<LeaveResponseDto>(leave);
response.StatusCode = 201;
}
catch (Exception ex)
{
response.Error = new ErrorResponseDto()
{
ErrorCode = 500,
Message = ex.Message
};
response.StatusCode = 500;
}
}
return response;
}
Currently, what I have will insert a new record for the Employee Leave Application into the database.
What I want to achieve is that I want to keep all the records of the Leave Applications for each employee.
At the point of insert, the application should check the last leave application record of that particular employee, change isCurrent to false, and then insert a new record, and the new record will have isCurrent as true.
How do I achieve this?
Thanks
You can retrieve the last record using LastOrDefault() and update it using EntityState.Modified
Try this
public async Task<GenericResponseDto<LeaveResponseDto>> CreateAsync(LeaveRequestDto request)
{
var response = new GenericResponseDto<LeaveResponseDto>();
var employee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == request.EmployeeId);
if (employee == null)
{
response.Error = new ErrorResponseDto()
{
ErrorCode = 404,
Message = "Employee does not exist in the system!"
};
response.StatusCode = 404;
}
else
{
var lastLeave = _context.Set<EmployeeLeave>().where(leave =>
leave.Employee.Id == request.EmployeeId ).LastOrDefault();
if(lastLeave != null)
{
lastLeave .IsCurrent = false;
_context.Entry(lastLeave).State = EntityState.Modified;
}
var leave = _mapper.Map<EmployeeLeave>(request);
leave.Employee = employee;
leave.IsCurrent = true;
try
{
_context.EmployeeLeaves.Add(leave);
await _context.SaveChangesAsync();
response.Result = _mapper.Map<LeaveResponseDto>(leave);
response.StatusCode = 201;
}
catch (Exception ex)
{
response.Error = new ErrorResponseDto()
{
ErrorCode = 500,
Message = ex.Message
};
response.StatusCode = 500;
}
}
return response;
}
I am sending data to HTTP post API. But everytime I try to call the API, I get error code: 400, Bad request message.
Here is my API code:
[Route("InsUpPlayer")]
[HttpPost]
public async Task<object> InsUpPlayer([FromForm] Players player)
{
try
{
//Some code here
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
And my repository code:
public async Task<string> PlayerInsUpPost(Player player1)
{
var SendResponse = "false";
try
{
var RequestUrl = baseUrl + "Master/InsUpPlayer";
var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(RequestUrl);
using (var player = new MultipartFormDataContent())
{
if (player1.ProfileImageFile != null)
{
string objimgFileBase64 = "";
ByteArrayContent fileContent;
using (var ms = new MemoryStream())
{
player1.ProfileImageFile.CopyTo(ms);
var fileBytes = ms.ToArray();
objimgFileBase64 = Convert.ToBase64String(fileBytes);
}
byte[] bytes = Convert.FromBase64String(objimgFileBase64);
fileContent = new ByteArrayContent(bytes);
player.Add(fileContent, "ProfileImageFile", string.Format("{0}", player1.ProfileImageFile.FileName));
}
if (player1.DetailImageFile != null)
{
string objimgFileBase64 = "";
ByteArrayContent fileContent;
using (var ms = new MemoryStream())
{
player1.DetailImageFile.CopyTo(ms);
var fileBytes = ms.ToArray();
objimgFileBase64 = Convert.ToBase64String(fileBytes);
}
byte[] bytes = Convert.FromBase64String(objimgFileBase64);
fileContent = new ByteArrayContent(bytes);
player.Add(fileContent, "DetailImageFile", string.Format("{0}", player1.DetailImageFile.FileName));
}
player.Add(new StringContent(player1.playerId.ToString()), "playerId");
player.Add(new StringContent(player1.FirstName), "FirstName");
player.Add(new StringContent(player1.LastName), "LastName");
player.Add(new StringContent(player1.DOB.ToString()), "DOB");
player.Add(new StringContent(player1.Nationality.ToString()), "Nationality");
player.Add(new StringContent(player1.BirthState.ToString()), "BirthState");
player.Add(new StringContent(player1.JerseyNo.ToString()), "JerseyNo");
player.Add(new StringContent(player1.Postion.ToString()), "Postion");
player.Add(new StringContent(player1.Biography), "Biography");
player.Add(new StringContent(player1.isActive.ToString()), "isActive");
player.Add(new StringContent(player1.isPublish.ToString()), "isPublish");
player.Add(new StringContent(player1.UserType.ToString()), "UserType");
HttpResponseMessage objResponse = await httpClient.PostAsync(RequestUrl, player);
if (objResponse.IsSuccessStatusCode && (int)objResponse.StatusCode == 200)
{
var serResponse = objResponse.ContentAsType<ResultModel>();
//SendResponse = serResponse.result;
SendResponse = "true";
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Exception Occured");
throw;
}
return SendResponse;
}
The Player class is like this:
public class Player
{
public long playerId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DOB { get; set; }
public int Nationality { get; set; }
public int BirthState { get; set; }
public int JerseyNo { get; set; }
public int Postion { get; set; }
public string Biography { get; set; }
public bool isActive { get; set; }
public bool isPublish { get; set; }
public int UserType { get; set; }
public IFormFile ProfileImageFile { get; set; }
public IFormFile DetailImageFile { get; set; }
public string ProfileImage { get; set; }
public string DetailImage { get; set; }
}
Update: Here is my JQuery code: The DOB here is correct, but I realized just now that it is not getting passed correctly to the controller.
$("#PublishPlayer").click(function () {
debugger;
var value = $('#CreatePlayerForm').valid();
var url = '/Admin/PlayerInsUpPost';
var day = $('#Day').val();
var month = $('#Month').val();
var year = $('#Year').val();
var DOB = new Date(year, month, day);
var fdata = new FormData();
fdata.append("playerId", $('#playerId').val());
fdata.append("FirstName", $('#FirstName').val());
fdata.append("LastName", $('#LastName').val());
fdata.append("DOB", DOB);
fdata.append("Nationality", $('#Nationality').val());
fdata.append("BirthState", $('#BirthState').val());
fdata.append("JerseyNo", $('#JerseyNo').val());
fdata.append("Position", $('#Position').val());
fdata.append("Biography", $('#Biography').val());
fdata.append('ProfileImageFile', $('#ProfileImageFile')[0].files[0]);
fdata.append('DetailImageFile', $('#ProfileImageFile')[0].files[0]);
if (value == true) {
$.ajax({
url: url,
datatype: "json",
accept: {
javascript: 'application/javascript'
},
type: "POST",
cache: false,
processData: false,
contentType: false,
data: fdata,
success: function (result) {
if (result == "true") {
alert('Player added successfully.');
window.location.href = "/Admin/PlayerList";
} else if (result == "false") {
alert('Failed to update, please try later.');
}
},
error: function () {
alert('Something went wrong');
}
});
}
else {
//$('.playeradd').removeClass('show');
//$('.playeradd').addClass('hide');
return false;
}
//event.stopPropagation();
});
The DOB in JQuery before calling Ajax is : Wed Sep 12 2001 00:00:00 GMT+0530 (India Standard Time) {}
When passed to controller it is: {01-01-0001 12:00:AM}
If I comment DOB in API and in the frontend, everything works fine. But I need to send DOB to API and I can't change the datatype of DOB in API. How do I fix this error?
When passing the data into the ajax request convert it to ISO string. Dotnet understands that. So do something like this:
fdata.append("DOB", DOB.toISOString());
I suppose it is some problem with ASP.NET deserialization of DateTime (I'm not sure tho). I have run into similar problem of sending dates before and my solution was instead of sending DateTime struct, I send number of ticks (which you can get from DateTime object) as long variable.
DateTime BOD = DateTime.Now; // You may fill your DateTime object with your own data
long BODticks = BOD.Ticks;
And then on the server side you can easily recreate date time like this:
DateTime myDate = new DateTime(BODticks);
And then in order to use it you can modify your player class as follows:
public class Player
{
public long playerId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public long DOBTicks { get; set; }
public DateTime DOB { get => new DateTime(DOBTicks); set => DOBTicks = value.Ticks; }
public int Nationality { get; set; }
public int BirthState { get; set; }
public int JerseyNo { get; set; }
public int Postion { get; set; }
public string Biography { get; set; }
public bool isActive { get; set; }
public bool isPublish { get; set; }
public int UserType { get; set; }
public IFormFile ProfileImageFile { get; set; }
public IFormFile DetailImageFile { get; set; }
public string ProfileImage { get; set; }
public string DetailImage { get; set; }
}
I'm sure someone could find a better solution though and that's assuming this one actually works and I understood your problem right.
The new serializer in .net core > 3.0 is strict when parsing date formats (note that the default has changed from newtonsoft json). They have to be in ISO8601 format, i.e. YYYY-MM-DD. If you are passing something that isn't in ISO8601 forms you have to write a custom formatter.
public class DateTimeJsonConverter : JsonConverter<DateTime>
{
public override DateTime Read(
ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options) =>
DateTime.ParseExact(reader.GetString(),
"<YOUR FORMAT HERE>", CultureInfo.InvariantCulture);
public override void Write(
Utf8JsonWriter writer,
DateTime dateTimeValue,
JsonSerializerOptions options) =>
writer.WriteStringValue(dateTimeValue.ToString(
"<YOUR FORMAT HERE>", CultureInfo.InvariantCulture));
}
The code above is an example of a custom formatter.
Read further details here (https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to#sample-basic-converter) in how to create a custom formatter for your input.
i want to loop my request and perform something for my array ( Cart ) but i dont know how to loop the request
here is the request
enter image description here
and here is the object class or the model for the request
public class OrderRRModel
{
public ObjectId id { get; set; }
public string cutomer_name { get; set; }
public string table_number { get; set; }
public List<ListCart> Cart { get; set; }
public OrderRRModel()
{
Cart = new List<ListCart>();
}
}
public class ListCart
{
public string product { get; set; }
public double amount { get; set; }
public double price { get; set; }
}
here is my full code
public ResponseModel<OrderRRModel> InsertOrderTest(string tokenAdmin, OrderRRModel entity)
{
var entityResult = new ResponseModel<OrderRRModel>();
try
{
var auth = _adminCollection.Find(x => x.token == tokenAdmin).FirstOrDefault();
if (auth != null)
{
var dates = DateTime.Now.ToUniversalTime();
// looping here
var check = _menuCollection.Find(x => x.product_name == cart.product_name).FirstOrDefault();
cart.price = check.price;
var result = _menuCollection.UpdateOne(
x => x.product_name == cart.product_name,
Builders<MenuRRModel>.Update.Set(x => x.updated_at, dates)
.Set(x => x.stock, check.stock - cart.amount) // updating stock by reducing stock based on quantity
);
// end of looping
_orderCollection.InsertOne(entity);
entityResult.Status = true;
entityResult.Messages.Add(new ResponseMessageModel()
{
Type = ResponseMessageModel.MessageType.SUCCESS,
Title = "Success",
Message = "Successful"
});
}
else
{
entityResult.Messages.Add(new ResponseMessageModel()
{
Type = ResponseMessageModel.MessageType.WARNING,
Title = "Action Failed",
Message = "Anda Tidak Memiliki Wewenang!"
});
}
}
catch (Exception ex)
{
entityResult.Messages.Add(new ResponseMessageModel()
{
Type = ResponseMessageModel.MessageType.ERROR,
Title = "Error",
Message = ex.Message
});
}
return entityResult;
}
can you guys tell me the code for looping my request ?
please be kind im a newbie
just do this
foreach (var cart in entity.cart)
{
cart.itemcart
}
[HttpGet]
public ActionResult Create()
{
Articles article = new Articles();
return View(article);
}
[HttpPost]
public ActionResult Create(Articles article)
{
try
{
article.Family = article.ArticleIDX; //그룹번호
article.Parent = 0; //순서
article.Depth = 1; //그룹내 최상위 글로부터 매겨지는 순서
article.Indent = 0; //들여쓰기
article.ModifyDate = DateTime.Now;
article.ModifyMemberID = User.Identity.Name;
db.Articles.Add(article);
db.SaveChanges();
if (Request.Files.Count > 0)
{
var attachFile = Request.Files[0];
if (attachFile != null && attachFile.ContentLength > 0)
{
var fileName = Path.GetFileName(attachFile.FileName);
var path = Path.Combine(Server.MapPath("~/Upload/"), fileName);
attachFile.SaveAs(path);
ArticleFiles file = new ArticleFiles();
file.ArticleIDX = article.ArticleIDX;
file.FilePath = "/Upload/";
file.FileName = fileName;
file.FileFormat = Path.GetExtension(attachFile.FileName);
file.FileSize = attachFile.ContentLength;
file.UploadDate = DateTime.Now;
db.ArticleFiles.Add(file);
db.SaveChanges();
}
}
ViewBag.Result = "OK";
}
catch (Exception ex)
{
Debug.WriteLine("Board");
Debug.WriteLine(ex.ToString());
ViewBag.Result = "FAIL";
}
return View(article);
//return RedirectToAction("ArticleList");
}
[HttpGet]
public ActionResult ReplyCreate(int aidx)
{
Articles articleReply = new Articles();
return View(articleReply);
}
[HttpPost]
public ActionResult ReplyCreate(Articles replyArticles)
{
Articles articles = new Articles();
try
{
//부모글 불러오기(글번호로 불러오기)
Articles note = db.Articles.Find(articles.ArticleIDX);
//Family는 원글의 번호
replyArticles.Family = replyArticles.ArticleIDX;
//Parent 순서
//Depth 는 답글의 글 번호
//Indent 들여쓰기
replyArticles.ModifyDate = DateTime.Now;
replyArticles.ModifyMemberID = User.Identity.Name;
db.Articles.Add(replyArticles);
db.SaveChanges();
ViewBag.Result = "OK";
}
catch (Exception ex)
{
ViewBag.Result = "FAIL";
}
return View(replyArticles);
}
public partial class Articles
{
[Key]
public int ArticleIDX { get; set; }
public int? Family { get; set; }
public int? Depth { get; set; }
public int? Indent { get; set; }
public int? Parent { get; set; }
[StringLength(200)]
public string Title { get; set; }
[Column(TypeName = "text")]
public string Contents { get; set; }
[StringLength(50)]
public string Category { get; set; }
[StringLength(20)]
public string ModifyMemberID { get; set; }
public DateTime? ModifyDate { get; set; }
public virtual Members Members { get; set; }
}
The above code is the code I implemented.
Articles created using the create method are stored in the database.
What do you do when you try to recall a post stored in the database with ReplyCreate?
The null value is often entered into the model.
I try to find it using the primary key, but the primary key also has a null value.
Articles note = db.Articles.Find(articles.ArticleIDX);
does not work because articles is an empty object, due to the line
Articles articles = new Articles();
just above. You never set any of the fields in this object, including the ArticleIDX, before calling the Find method.
I think you probably intended to search using the value passed in to the controller? In that case it would need to be
Articles note = db.Articles.Find(replyArticles.ArticleIDX);
because replyArticles is the variable which was received from the browser in the request. I assume this contains a value in the ArticleIDX field.
Having said that, I don't know what the purpose of this line of code is, because you never use the note object in any of the following code, so I don't know why you needed to find it.