Import the values stored in the database from the controller - c#

[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.

Related

How to Insert an "Employee Leave Application" into DB and update the last inserted record based on Condition

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;
}

How to design nested class properly?

I generate 2 class looked like this :
public class mPromotionDetail
{
public long PromotionDetailId { get; set; }
public long PromotionHeaderId { get; set; }
public long PromotionTypeId { get; set; }
public string PromotionTypeName { get; set; }
public string VendorCode { get; set; }
public string VendorName { get; set; }
public bool Active { get; set; }
public List<mPromotionDetailArticle> RequestDetailArticles { get; set; }
public static List<mPromotionDetail> Get(long PromotionDetailId = 0, long PromotionHeaderId = 0, long PromotionTypeId = 0, string VendorCode = "", bool Active = true)
{
try
{
Hashtable htParam = new Hashtable();
htParam.Add("#PromotionDetailId", PromotionDetailId);
htParam.Add("#PromotionHeaderId", PromotionHeaderId);
htParam.Add("#PromotionTypeId", PromotionTypeId);
htParam.Add("#VendorCode", VendorCode);
htParam.Add("#Active", Active);
DataSet ds = DB.ExecuteSP_Ds("udsp_GetPromotionDetail", htParam);
return ds.Tables[0].AsEnumerable().Select(row => new mPromotionDetail
{
PromotionDetailId = row["PromotionDetailId"],
PromotionHeaderId = row["PromotionHeaderId"],
PromotionTypeId = row["PromotionTypeId"],
PromotionTypeName = row["PromotionTypeName"],
VendorCode = row["VendorCode"],
VendorName = row["VendorName"],
Active = row["active"],
RequestDetailArticles = mPromotionDetailArticle.Get(PromotionDetailId: Shared.NtL(row["PromotionDetailId"]), Active: true)
}).ToList();
}
catch (Exception ex)
{
throw ex;
}
}
}
public class mPromotionDetailArticle
{
public long PromotionDetailArticleId { get; set; }
public long PromotionDetailId { get; set; }
public string ArticleCode { get; set; }
public string ArticleDescription { get; set; }
public long Qty { get; set; }
public string UoM { get; set; }
public decimal NormalPrice { get; set; }
public decimal SpecialPrice { get; set; }
public bool Active { get; set; }
public static List<mPromotionDetailArticle> Get(long PromotionDetailArticleId = 0, long PromotionDetailId = 0, long PromotionHeaderId = 0, bool Active = true)
{
try
{
Hashtable htParam = new Hashtable();
htParam.Add("#PromotionDetailArticleId", PromotionDetailArticleId);
htParam.Add("#PromotionDetailId", PromotionDetailId);
htParam.Add("#PromotionHeaderId", PromotionHeaderId);
htParam.Add("#Active", Active);
DataSet ds = DB.ExecuteSP_Ds("udsp_GetPromotionDetailArticle", htParam);
return ds.Tables[0].AsEnumerable().Select(row => new mPromotionDetailArticle
{
PromotionDetailArticleId = row["PromotionDetailArticleId"],
PromotionDetailId = row["PromotionDetailId"],
ArticleCode = row["ArticleCode"],
ArticleDescription = row["ArticleDescription"],
Qty = row["Qty"],
UoM = row["UoM"],
NormalPrice = row["NormalPrice"],
SpecialPrice = row["SpecialPrice"],
Active = row["active"]
}).ToList();
}
catch (Exception ex)
{
throw ex;
}
}
}
Note that ExecuteSP_Ds is just calling my SQL SP and returns DataSet.
This works just fine. But if mPromotionDetail.Get returns many rows (ex: 1000 rows), it means mPromotionDetailArticle.Get will be executed just as much time.
Is there any way to design this more properly and efficiently?
Thank you
You could start by decoupling your database code from your entities, some good, and tested ways to do it are by using some of the following patterns:
DAOs
Repositories
For further research I recommend you to read this article:
MSDN - Persistence Patterns
There it also speaks about Lazy and Eager loading, that way you could minimize the workload and size of your database call.
Finally it be good for you to read about the SOLID Principles, some good places are:
Scotch.io SOLID
Solid Principles Succintly
Solid Using C#
If we are talking hundreds/thousands of rows on your call to these procs, consider having the procs take paging parameters (e.g. pageNumber, rowsPerPage). Then modify your proc to use this paging parameters. You can search in SO about how to apply paging in your queries.
Your other option, is to have your proc return multiple results sets and then just do the object mapping of your master-details data in the code.

Losing data during transfer from one action to another

I'm losing data during transfer from one action to another
What's wrong? I'm doing this:
public ActionResult Index(CV model)
{
return View();
}
public ActionResult rr()
{
CV _cv = new CV();
_cv.education = new List<Education>();
_cv.education.Add(new Education()
{
Faculty = "sa",
OnGoing = false,
Specialization = "asdasd",
UniversityName = "sulxan",
EndDate = DateTime.Now.AddDays(1),
StartDate = DateTime.Now
});
return RedirectToAction("Index", _cv);
}
And when I'm debugging to Index parameter model.education.count = 0 instead of 1. In rr action it's 1 with desired values.
My model class is:
public class CV
{
public List<Education> education { get; set; }
public Education newEducation { get; set; }
}
public class Education
{
public string UniversityName { get; set; }
public string Faculty { get; set; }
public string Specialization { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public bool OnGoing { get; set; }
}
Posting an answer because I'm too much of a noob to comment.
What Stephen Muecke said in his comment is totally correct - and, it's definitely important to persist your data. One other thing to note is that, based on the code you posted, you don't need the RedirectToAction if all you are trying to do is return the model with the view you want:
return View("Index", _cv);
Of course, without seeing how the rest of your app is built, that could potentially cause an issue.
You can use tempdata to store the entity and retrieve the data.use this code
public ActionResult Index()
{
CV model = (CV)TempData["cv"];
return View();
}
public ActionResult rr()
{
CV _cv = new CV();
_cv.education = new List<Education>();
_cv.education.Add(new Education()
{
Faculty = "sa",
OnGoing = false,
Specialization = "asdasd",
UniversityName = "sulxan",
EndDate = DateTime.Now.AddDays(1),
StartDate = DateTime.Now
});
TempData["cv"] = _cv;
return RedirectToAction("Index");
}
You can use tempdata
like this
public ActionResult Index()
{
var model = TempData["CV "] as CV;
return View();
}
public ActionResult rr()
{
CV _cv = new CV();
_cv.education = new List<Education>();
_cv.education.Add(new Education()
{
Faculty = "sa",
OnGoing = false,
Specialization = "asdasd",
UniversityName = "sulxan",
EndDate = DateTime.Now.AddDays(1),
StartDate = DateTime.Now
});
TempData["CV"] = _cv;
return RedirectToAction("Index");
}

How do I extend a model class to another model?

I am trying to extend a class to another class that will collect them as a list.
model:
public class Brand
{
public int BrandId { get; set; }
public string Name { get; set; }
public string Guid { get; set; }
public float Rating { get; set; }
public string Industry { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Postal { get; set; }
public string CountryCode { get; set; }
public virtual Snapshot Snapshot { get; set; }
}
public class Snapshot
{
public int ID { get; set; }
public string Guid { get; set; }
public int CompanyID { get; set; }
public string CompanyName { get; set; }
public string Email { get; set; }
public DateTime DateTimeSent { get; set; }
public string Subject { get; set; }
public string Html { get; set; }
public string Image { get; set; }
public string Unsubscribe { get; set; }
}
public class BrandSnaphotViewModel
{
public Brand Brand { get; set; }
public List<Snapshot> SnapshotItems { get; set; }
}
controller:
public ActionResult Index(string brandGuid)
{
BrandSnaphotViewModel viewModel = new BrandSnaphotViewModel();
Brand brand = GetBrand(brandGuid);
viewModel.Brand = brand;
List<Snapshot> snapshot = GetBrandSnapshots(brand.BrandId);
viewModel.SnapshotItems = snapshot;
List<BrandSnaphotViewModel> viewModelList = new List<BrandSnaphotViewModel>();
viewModelList.Add(viewModel);
return View(viewModelList.AsEnumerable());
}
private Brand GetBrand(string brandGuid)
{
Brand brand = new Brand();
string dbConnString = WebConfigurationManager.ConnectionStrings["dbConn"].ConnectionString;
MySqlConnection dbConn = new MySqlConnection(dbConnString);
dbConn.Open();
MySqlCommand dbCmd = new MySqlCommand();
dbCmd.CommandText = "SELECT *, industries.name AS industry_name FROM brands LEFT JOIN industries ON brands.industry_id = industries.industry_id WHERE brand_guid = '" + brandGuid.ToString() + "' AND private = 0 LIMIT 1";
dbCmd.Connection = dbConn;
MySqlDataReader dbResult = dbCmd.ExecuteReader();
if (dbResult.Read())
{
brand.Guid = dbResult["brand_guid"].ToString();
brand.BrandId = Convert.ToInt32(dbResult["brand_id"]);
brand.Industry = dbResult["industry_name"].ToString();
}
dbResult.Close();
dbConn.Close();
return brand;
}
private List<Snapshot> GetBrandSnapshots(int brandId)
{
string dbConnString = WebConfigurationManager.ConnectionStrings["dbConn"].ConnectionString;
MySqlConnection dbConn = new MySqlConnection(dbConnString);
dbConn.Open();
MySqlCommand dbCmd = new MySqlCommand();
dbCmd.CommandText = "SELECT * FROM snapshots WHERE brand_id = " + brandId + " AND archive = 0 ORDER BY date_sent DESC";
dbCmd.Connection = dbConn;
MySqlDataReader dbResult = dbCmd.ExecuteReader();
List<Snapshot> snapshots = new List<Snapshot>();
while (dbResult.Read())
{
snapshots.Add(new Snapshot
{
SnapshotId = Convert.ToInt32(dbResult["snapshot_id"]),
Subject = dbResult["subject"].ToString(),
DateTimeSent = Convert.ToDateTime(dbResult["date_sent"]),
Image = dbResult["image"].ToString(),
Email = dbResult["email"].ToString(),
ContentType = dbResult["content_type"].ToString(),
Type = dbResult["type"].ToString()
});
}
dbResult.Close();
dbConn.Close();
return snapshots;
}
edit
FIXED
The issue was the VIEW was not referencing the ViewModel as an IENumerable<>. FACEPALM.
#model IEnumerable<projectvia.ViewModels.BrandSnaphotViewModel>
#{
ViewBag.Title = "Index";
}
#foreach(var item in Model)
{
#item.Brand.Guid;
for(int i = 0; i< #item.SnapshotItems.Count; i++)
{
#item.SnapshotItems[i].Subject<br/>
}
}
That resolved the issue.
Thank you both experts for the insights... i took both advice and came to this solution.
you are doing wrong, it is a list.
you cannot add element this way. Create object and add that object in list by calling Add()
do like this to add items in it:
List<BrandEmailList> brandSnapshotsList = new List<BrandEmailList>();
while (dbResult.Read())
{
BrandEmailList brandSnapshots = new BrandEmailList (); // create an object
brandSnapshots.ID = Convert.ToInt32(dbResult["snapshot_id"]);
brandSnapshots.Guid = dbResult["snapshot_guid"].ToString();
brandSnapshots.DateTimeSent = dbResult["date_sent"];
brandSnapshots.Subject = dbResult["subject"].ToString();
brandSnapshots.Image = dbResult["image"];
brandSnapshotsList.Add(brandSnapshots); // add it in list
}
EDIT:
List is a generic thing, you don't need to create a class for it. you can just instantiate a list and add items in it.
why are you doing like that you can do it this way simply:
List<Snapshot> brandSnapshotsList = new List<Snapshot>();
while (dbResult.Read())
{
Snapshot brandSnapshots = new Snapshot(); // create an object
brandSnapshots.ID = Convert.ToInt32(dbResult["snapshot_id"]);
brandSnapshots.Guid = dbResult["snapshot_guid"].ToString();
brandSnapshots.DateTimeSent = dbResult["date_sent"];
brandSnapshots.Subject = dbResult["subject"].ToString();
brandSnapshots.Image = dbResult["image"];
brandSnapshotsList.Add(brandSnapshots); // add it in list
}
Building on what Ehsan Sajjad did, looking at public IEnumerator<Snapshot> BrandEmails, i believe what you look for looks more like this:
public class Snapshot
{
public int ID { get; set; }
public string Guid { get; set; }
// ...
}
public class BrandEmailList : List<Snapshot>
{
}
You need not even create a new type for your brand email list, you can use List<Snapshot> directly.
public ViewResult Whatever() {
var brand = GetBrand(brandName);
var brandSnapshots = GetBrandSnapshots();
return View(brand, brandSnapshots);
}
private Brand GetBrand(string brandName)
{
try
{
var brand = new Brand();
brand.Name = brandName;
// database stuffs ...
return brand;
}
catch (Exception ex)
{
throw ex;
}
}
private List<Snapshot> GetBrandSnapshots()
{
// ...
// DB stuffs -- that *really* should not be in the controller anyways.
// ...
var snapshots = new List<BrandEmailList>();
while (dbResult.Read())
{
// object initializer syntax
snapshots.Add(new Snapshot {
ID = Convert.ToInt32(dbResult["snapshot_id"]),
Guid = dbResult["snapshot_guid"].ToString(),
DateTimeSent = dbResult["date_sent"],
Subject = dbResult["subject"].ToString(),
Image = dbResult["image"],
});
}
return snapshots
}
As a side note, mixing database access into controller methods can be a bad idea. It does not have to be, but it can be. Generally, fetching data from the database happens at a different "level" than serving a MVC result. MVC controller don't have the "purpose" to talk to a database, that work can/should be delegated to a dedicated type. Compare the single responsibility principle part of the SOLID principles.

Request.CreateResponse returns blank data to postman

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!

Categories