I have a problem in regarding my TempData["Something"] because I want to customize every content of the Something. Below is my code:
Controller
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> SaveLoanContract(ModelLoan lc, string message)
{
var myList = new ModelLoan();
var countLoan = _Context.LoanContract.Count(c => c.EmployeeId == lc.loanContract.EmployeeId && c.LoanTypeId == lc.loanContract.LoanTypeId);
if (ModelState.IsValid)
{
//Some Logic
TempData["SuccessMessage"] = new { CssClassName = "alert-success", Title = "Success!", Message = "You have successfully applied. Please wait for confirmation. Thank you!" };
return RedirectToAction("Index");
}
}
View:
#if(TempData["SuccessMessage"] != null)
{
<div class="alert #TempData["SuccessMessage"].CssClassName">
<strong>#TempData["SuccessMessage"].Title</strong> #TempData["SuccessMessage"].Message
</div>
}
But I got an error on some objects CssClassName, Title, Message in TempData["SuccessMessage"] and I don't have any idea yet why. I know there is a small trick to fix this. Can someone help me with this? Thanks!
you cannot store anonymous type into TempData but you can create a class and convert tempdata to the class like this
public class ClsMsg
{
public string CssClassName { get; set; }
public string Title { get; set; }
public string Message { get; set; }
}
in action
TempData["SuccessMessage"] = new ClsMsg { CssClassName = "alert-success", Title = "Success!", Message = "You have successfully applied. Please wait for confirmation. Thank you!" };
and in view
#if (TempData["SuccessMessage"] != null)
{
ClsMsg msg = TempData["SuccessMessage"] as ClsMsg;
<div class="alert #msg.CssClassName">
<strong>#msg.Title</strong> #msg.Message
</div>
}
Related
I am a newbie to spring boot and thymeleaf,
I have a list of books ina table with checkboxes, I am not sure how to pass selected booksId s from the view to the controller and use them by the borrow or Return bttons? could you please help?
Here is my Html file https://wtools.io/paste-code/b5g4
and this is the relevant part from my bookService implementation :
public void borrowBook(String userEmail, String bookIds, Model model) {
if (!CollectionUtils.isEmpty(books)) {
User user = userRepository.findByEmail(userEmail);
List<String> requestedBooks = getRequestedBookIds(bookIds);
List<Book> borrowedBooks = new ArrayList<>();
List<Book> invalidBooks = new ArrayList<>();
for (Book book : books) {
if (requestedBooks.contains(book.getId()) && !book.isBorrowed() && user != null) {
book.setBorrowed(true);
book.setBorrowedBy(user.getFirstName());
borrowedBooks.add(book);
model.addAttribute("bookStatus", "Book BOrrowed By " + user.getFirstName());
} else {
invalidBooks.add(book);
model.addAttribute("bookStatus", "No Books are available");
}
}
model.addAttribute("inValidBooks", invalidBooks);
model.addAttribute("bookList", borrowedBooks);
}
}
#SuppressWarnings("unchecked")
private List<String> getRequestedBookIds(String bookIds) {
List<String> requestedBookIds = null;
try {
requestedBookIds = new ObjectMapper().readValue(bookIds, ArrayList.class);
} catch (Exception e) {
e.printStackTrace();
}
return !CollectionUtils.isEmpty(requestedBookIds) ? requestedBookIds : new ArrayList<>();
}
and this is from the controller:
#GetMapping(value = "/available", produces = MediaType.APPLICATION_JSON_VALUE)
public String getAvailableFreeBooks(Model model) {
List<Book> availableBooks= bookService.getAllAvailaBooks();
model.addAttribute("listBooks", availableBooks);
return "available_books";
}
In your html you would probably:
<input type="checkbox" th:field="*{requestedBooks}" value="${book.getId}">
omit the id (if you don't need it).
use th:field (instead of name).
set value to the id of the current book.
In your controller: requestedBooks (#ModelAttribute("requestedBooks") List<String> requestedBooks) will (should) contain all checked book ids.
Ref: https://www.thymeleaf.org/doc/tutorials/2.1/thymeleafspring.html#checkbox-fields
A sample repository:
https://github.com/xerx593/soq67602860
Uppdate:
To process the checkboxes client-sided (jquery),
you can obtain an array of ids like:
<script language="javascript" type="text/javascript">
$(document).ready(function () {
$("#btnBorrow").click(function() {
var reqBookIds = new Array();
$('input[name="requestedBooks"]:checked').each(function() {
reqBookIds .push(this.value);
});
alert("Number of selected Books: "+reqBookIds .length+"\n"+"And, they are: "+reqBookIds);
// do stuff with reqBookIds ...
)};
});
</script>
With the mentioned <input type="checkbox" .../> (consider that <input/> should be inside a <form/>!!) and a button like:
<button id="btnBorrow">Borrow</button>
..the userEmail must come from client side???
I've already successfully got the full name of a user using json:
#region get facebook name
//PUBLIC STATICS
public static string fbname;
private static string get_data;
public static string GetUserFBName()
{
FB.API("me?fields=name", Facebook.HttpMethod.GET, UserCallBack);
return fbname;
}
//USER CALLBACK
private static void UserCallBack(FBResult result)
{
if (result.Error != null)
{
get_data = result.Text;
}
else
{
get_data = result.Text;
}
var dict = Json.Deserialize(get_data) as IDictionary;
fbname = dict["name"].ToString();
}
#endregion
Now where do I begin with getting the email adress? I added the following to the permission:
FB.Login("email", AuthCallBack);
Thanks!
I am using view model to display a dropdownlist and i am also trying to get the value of the selected list, here is my view model
public class CreateJobViewModel
{
public int[] SelectedIndustriesIds { get; set; }
public IList<SelectListItem> IndustriesList { get; set; }
}
My controller
public ActionResult Create()
{
var industryList = repository.GetAllIndustries();
var model = new CreateJobViewModel
{
IndustriesList = industryList.Select(i => new SelectListItem
{
Value = i.IndustryId.ToString(),
Text = i.Name
}).ToList()
};
return View("~/Views/Dashboard/Job/Create.cshtml", model);
}
My post controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CreateJobViewModel model)
{
try
{
var job = new Job()
{
Title = "hi",
EmploymentHourId = 1,
LocationId = 1,
Salary = 50,
SalaryPeriodId = 1,
PostCode = 2131,
Role = "world",
Description = "hello",
IsPublished = false,
ShiftId = 1,
WorkDayId = 1,
NumberOfPosition = 5,
Meal = false,
SecondYearVisa = true,
Sponsorship = true,
Accommodation = true,
DurationId = 1,
IndustryExperiencePeriod = 5,
Id = User.Identity.GetUserId(),
};
foreach (int id in model.SelectedIndustriesIds)
{
var industry = repository.Industry(id);
job.Industries.Add(industry);
}
foreach (int id in model.SelectedSpecialRequirementsId)
{
var special = repository.SpecialRequirement(id);
job.SpecialRequirements.Add(special);
}
repository.AddJob(job);
return RedirectToAction("Create");
}
catch
{
return View("~/Views/Dashboard/Job/Create.cshtml");
}
}
Every time i try to submit the selected value, i get Object reference not set to an instance of an object Error on the following line in my view:
#model Taw.WebUI.Models.CreateJobViewModel
#Html.ListBoxFor(m => m.SelectedIndustriesIds, Model.IndustriesList) -- here i get the error
Any reason why?
When you submit the form your throwing an exception (confirmed in the comments) and in the catch block you are returning the view, which throws the exception you are seeing because Model.IndustriesList is null. You need to re-assign the value before you return the view.
Since you need to assign SelectLists in the GET method and in the POST method if you return the view, I tend to re-factor this to a separate method to keep the controller code a bit cleaner. Note the following code is based on your model property being public SelectList IndustriesList { get; set; } which is a bit simpler than building IList<SelectListItem>
private void ConfigureViewModel(CreateJobViewModel model)
{
var industryList = repository.GetAllIndustries();
model.IndustriesList = new SelectList(industryList, "IndustryId", "Name")
// any other common stuff
}
and then in the action methods
public ActionResult Create()
{
var model = new CreateJobViewModel();
ConfigureViewModel(model);
return View(model);
}
public ActionResult Create(CreateJobViewModel model)
{
try
{
....
}
catch
{
ConfigureViewModel(model);
return View(model);
}
}
Note its also good practice to test if the model is valid before attempting to save it
public ActionResult Create(CreateJobViewModel model)
{
if (!ModelState.IsValid)
{
ConfigureViewModel(model);
return View(model); // return the view so the user can correct validation errors
}
....
First off, I'm new to breeze/angular...after reading some blogs and watching some pluralsight videos, I (like everybody else I guess) was so excited, but after a few weeks of trying, I started hating it because I'm running from one problem to the other. Is this technology still too early to learn and use?
Here is my data structure:
public class TshirtOrder
{
public int Id { get; set; }
public virtual Student Student { get; set; }
public virtual ICollection<OrderItem> OrderItems { get; set; }
}
public class OrderItem
{
public int Id { get; set; }
[ForeignKey("Type")]
public int TshirtTypeId { get; set; }
public virtual TshirtType Type { get; set; }
[ForeignKey("Size")]
public int TshirtSizeId { get; set; }
public virtual TshirtSize Size { get; set; }
public double UnitPrice { get; set; }
public int Quantity { get; set; }
[ForeignKey("TshirtOrder")]
public int TshirtOrderId { get; set; }
public TshirtOrder TshirtOrder { get; set; }
}
This is related breeze datacontext.js:
function _createTshirtOrder() {
var order = manager.createEntity("TshirtOrder");
order.tshirtItems = [];
order.tshirtItems.push(createOrderItem(lookups.tshirtTypes[0], lookups.tshirtSizes[0], 10));
common.saveEntity(order);
return order;
function createOrderItem(type, size, unitPrice) {
var item = manager.createEntity("OrderItem");
item.type = type;
item.size = size;
item.unitPrice = unitPrice;
item.quantity = 0;
return item;
}
}
When trying to save it at common.saveEntity(order), I got the error
Error: Error while interpolating: {{tshirtOrder.orderItems[0]}}
TypeError: Converting circular structure to JSON
The error complains about the circular structure, but I don't have any circular structure at all. In fact, the structure is very standard one and I had the almost same structure working a couple weeks earlier in another trial project. I'm not sure if the new libraries I'm using now has introduced some new defects.
I know this question has been asked, but I checked all answers and couldn't find my solution. The most relevant one is here, and this is the accepted solution:
var cache = [];
JSON.stringify(o, function(key, value) {
if (typeof value === 'object' && value !== null) {
if (cache.indexOf(value) !== -1) {
// Circular reference found, discard key
return;
}
// Store value in our collection
cache.push(value);
}
return value;
});
cache = null; // Enable garbage collection
However, it doesn't work for me. As I debug through it, I realize (cache.indexOf(value) !== -1) is never true in my case.
Your help is much appreciated.
Update:
This is my saveEntity() method:
function _saveEntity(masterEntity) {
// if nothing to save, return a resolved promise
if (!manager.hasChanges()) { return $q(); }
var description = describeSaveOperation(masterEntity);
return manager.saveChanges().then(saveSucceeded).fail(saveFailed);
function describeSaveOperation(entity) {
var statename = entity.entityAspect.entityState.name.toLowerCase();
var typeName = entity.entityType.shortName;
var title = entity.title;
title = title ? (" '" + title + "'") : "";
return statename + " " + typeName + title;
}
function saveSucceeded() {
logger.logInfo("saved " + description);
}
function saveFailed(error) {
var msg = "Error saving " + description + ": " + getErrorMessage(error);
masterEntity.errorMessage = msg;
logger.logError(msg);
// Let user see invalid value briefly before reverting
$timeout(function () { manager.rejectChanges(); }, 1000);
throw error; // so caller can see failure
}
function getErrorMessage(error) {
var reason = error.message;
if (reason.match(/validation error/i)) {
reason = getValidationErrorMessage(error);
}
return reason;
}
function getValidationErrorMessage(error) {
try { // return the first error message
var firstItem = error.entitiesWithErrors[0];
var firstError = firstItem.entityAspect.getValidationErrors()[0];
return firstError.errorMessage;
} catch (e) { // ignore problem extracting error message
return "validation error";
}
}
}
Where manager is
var manager = new breeze.EntityManager("api/Breeze");
What is the code behind common.saveEntity(order)? Are you going thru the EntityManager.saveChanges method?
In my webapp
webApp
\Views
\Views\School
\Views\School\School.cshtml
\Views\School\Schools.cshtml
In Request and Response classes:
[Route("/v1/school", Verbs = "POST")]
[DefaultView("School")]
public class SchoolAddRequest : School, IReturn<SchoolResponse>
{
}
public class SchoolResponse
{
public School School { get; set; }
public SchoolResponse()
{
ResponseStatus = new ResponseStatus();
Schools = new List<School>();
}
public List<School> Schools { get; set; }
public ResponseStatus ResponseStatus { get; set; }
}
In SchoolService.cs:
[DefaultView("School")]
public class SchoolService: Service
{
public SchoolResponse Post(SchoolAddRequest request)
{
var sch = new School {Id = "10"};
return new SchoolResponse {School = sch, ResponseStatus = new ResponseStatus()};
}
}
In school.cshtml:
#inherits ViewPage<Test.Core.Services.SchoolResponse>
#{
Layout = "_Layout";
}
<form action="/v1/School" method="POST">
#Html.Label("Name: ") #Html.TextBox("Name")
#Html.Label("Address: ") #Html.TextBox("Address")
<button type="submit">Save</button>
</form>
#if (#Model.School != null)
{
#Html.Label("ID: ") #Model.School.Id
}
On the browser:
This is suppose to work but it is not, i get a blank page
http://test/school/
This works:
http://test/views/school/
On hitting the 'save' btn the required response is returned but the url on the browser is :
http://test/v1/School
I was expecting it to be:
http://test/School
How can i get the url to work right.? Shouldn't it be
http://test/School on request and response.
http://test/school/ is not returning anything because you don't have a request DTO and a corresponding 'Get' service implemented for the route.
What you need is a request DTO:
[Route("/school", Verbs = "GET")]
public class GetSchool : IReturn<SchoolResponse>
{
}
and the service...
public SchoolResponse Get(GetSchool request)
{
var sch = new School {Id = "10"};
return new SchoolResponse {School = sch, ResponseStatus = new ResponseStatus()};
}
When you hit 'Save', a 'POST' request will be made to the server through the route 'v1/school' because the form tag you specified has:
<form action="/v1/School" method="POST">
Hope this helps.