ASP.Net throws an error but still posts the data - asp.net

We are making a movie rating web application but we come across the error Object reference not set to an instance of an object. even though we get that error when we navigate back to the ratings page the rating got added.
Contoller:
public ActionResult RateMedia(string Item, int Rate)
{
PopMediaDDL();
var userStore = new UserStore<ApplicationUser>(ldb);
var manager = new UserManager<ApplicationUser>(userStore);
var user = manager.FindById(User.Identity.GetUserId());
MediaRating rate = new MediaRating();
rate.Title = ldb.MediaData.First(c => c.MediaName == Item);
rate.Rating = Rate;
rate.RateFor = user;
ldb.MediaRatingData.Add(rate);
ldb.SaveChanges();
return View();
}
Model:
public class MediaRating
{
[Key]
public int MediaRatingID { get; set; }
public virtual ApplicationUser RateFor { get; set; }
public virtual Media Title { get; set; }
public int Rating { get; set; }
}
View:
#using CollectionCompanion.Extensions
#using CollectionCompanion.Models;
#model CollectionCompanion.Models.UserCollectionItem
<h2>Rate Media!</h2>
<hr />
#using (Html.BeginForm())
{
<div style="width:80%;">
<div id="AddColItem">
#Html.AntiForgeryToken()
#Html.TextBoxFor(m => m.Item, new { #id = "MediaItem",#style= "color:black;", #name = "MediaItem", #class = "form-control" })
</div>
<div id="AddColDD">
<select id="Rate" name="Rate">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</div>
<div id="AddColBTN">
<input type="hidden" name="UserCollection" value="#ViewBag.UserCollectionID" />
<button type="submit" class="btn btn-default btn-info"><span class="glyphicon glyphicon-plus"></span> Add</button>
</div>
</div>
}
#foreach (MediaRating rating in ViewBag.Ratings)
{
<div>
<div style="width:50%;">
#rating.Title.MediaName
</div>
<div style="width:50%">
#rating.Rating
</div>
</div>
}
<script type="text/javascript">
$("#MediaItem").autocomplete({
change: function (event, ui) { },
source: "../../Media/GetMediaResult/",
minLength: 2
}
);
</script>

You are returning the view without a model at the end of your controller action:
return View();
I suspect that you are getting a null reference exception because you're not providing the model nor the ViewBag required to populate the View. It should look similar to the HttpGet controller action as that is providing everything required to build the View in the first place.

Related

Model coming through as null in controller

I have a relatively simple form that's posting to a controller, yet the model is coming through as null every time and I don't understand why. I'm using Umbraco CMS (so please ignore any Umbraco references if they're not relevant) and jquery combined with an image plugin (Filepond) to post the data. This is my model:
public class PropertyViewModel: PublishedContentWrapped
{
public PropertyViewModel(IPublishedContent content, IPublishedValueFallback publishedValueFallback) : base(content, publishedValueFallback)
{
this.Countries = GetCountries();
}
[Required]
public string Country { get; set; }
[Required]
public string DisplayName { get; set; }
[Required]
public string Summary { get; set; }
[Required]
public string Description { get; set; }
[Required(ErrorMessage = "Please select at least one image")]
public List<IFormFile> Images { get; set; }
public SelectList Countries { get; set; }
public SelectList GetCountries()
{
List<string> countryNames = Bia.Countries.Iso3166.Countries.GetAllActiveDirectoryNames();
var countries = new List<SelectListItem>();
foreach (var country in countryNames)
countries.Add(new SelectListItem { Text = country, Value = country });
return new SelectList(countries, "Text", "Value");
}
}
Here is the controller:
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateUmbracoFormRouteString]
public async Task<IActionResult> HandleAddProperty(PropertyViewModel model)
{
if (ModelState.IsValid == false)
{
return CurrentUmbracoPage();
}
// Carry on execution..
}
Finally, here is my view. I should mention that model is a new instance of the PropertyViewModel class:
#using (Html.BeginUmbracoForm<PropertySurfaceController>("HandleAddProperty", null, new { #id = "form-add" }))
{
<div asp-validation-summary="All" class="text-danger"></div>
<div class="mb-3">
<select asp-for="#Model.Country" asp-items="Model.Countries" class="form-select">
<option value="">Select country</option>
</select>
<span asp-validation-for="#Model.Country" class="form-text text-danger"></span>
</div>
<div class="mb-3">
<label asp-for="#Model.DisplayName" class="form-label"></label>
<input asp-for="#Model.DisplayName" class="form-control" aria-required="true" />
<span asp-validation-for="#Model.DisplayName" class="form-text text-danger"></span>
</div>
<div class="mb-3">
<label asp-for="#Model.Summary" class="form-label"></label>
<textarea asp-for="#Model.Summary" class="form-control" aria-required="true"></textarea>
<span asp-validation-for="#Model.Summary" class="form-text text-danger"></span>
</div>
<div class="mb-3">
<label asp-for="#Model.Description" class="form-label"></label>
<textarea asp-for="#Model.Description" class="form-control" aria-required="true"></textarea>
<span asp-validation-for="#Model.Description" class="form-text text-danger"></span>
</div>
<div class="mb-3">
<input type="file" class="filepond" id="file" name="filepond" multiple data-max-file-size="5MB" data-max-files="10" accept="image/png, image/jpeg, image/gif">
</div>
<button type="submit" class="btn btn-primary" id="submit">Submit</button>
}
<script>
$(document).ready(function(e){
FilePond.registerPlugin(
FilePondPluginImageResize,
FilePondPluginFileValidateSize
);
var pond = FilePond.create(
document.querySelector('#file'), {
allowMultiple: true,
instantUpload: false,
allowProcess: false,
imageResizeTargetWidth: 1280,
imageResizeUpscale: false,
imageResizeMode: 'contain'
});
$("#form-add").submit(function (e) {
e.preventDefault();
var formdata = new FormData(this);
// append FilePond files into the form data
var pondFiles = pond.getFiles();
for (var i = 0; i < pondFiles.length; i++) {
formdata.append('Images', pondFiles[i].file);
}
console.log('formdata', formdata);
$.ajax({
url: "/umbraco/surface/PropertySurface/HandleAddProperty",
data: formdata,
dataType: 'JSON',
processData: false,
contentType: false,
method:"post"
}).done(function (response) {
// todo
});
})
});
</script>
When I inspect in Chrome to see what data is being sent to the server I can see the following:
So I can see the fields are matching the model, yet it's still coming through as null. I can't figure out where it's failing.
I've tried using [FromBody] and [FromForm] with the controller parameter, but it made no difference.
Is anyone able to spot where I'm going wrong?
I think the second parameter in BeginUmbracoForm is supposed to be the model, not null. So:
#using (Html.BeginUmbracoForm<PropertySurfaceController>("HandleAddProperty", new { #id = "form-add" }))
{ ... }

Dropdown Data Binding Problem in ASP.NET Core 6 MVC

I am using SelectListItem in the controller for binding my dropdown data. All the dropdown options are showing perfectly in the dropdown list, but when I try to save, the problem occurs. It's not adding the dropdown options data rather than its adding dropdown data's id.
All the related models, controller and views are shown here:
BuyerSelectList model class:
public class BuyerSelectList
{
[Key]
public int Id { get; set; }
[DisplayName("BUYER")]
public string Buyer { get; set; }
}
ItemSelectList model class:
public class ItemSelectList
{
[Key]
public int Id { get; set; }
[DisplayName("ITEM")]
public string Item { get; set; }
}
BTBNewLien2 model class:
public class BTBNewLien2
{
public int Id { get; set; }
[Required]
[DisplayName("Buyer")]
public int BuyerSelectListId { get; set; }
[ForeignKey("BuyerSelectListId")]
[ValidateNever]
public BuyerSelectList BuyerSelectList { get; set; }
[Required]
[DisplayName("Item")]
public int ItemSelectListId { get; set; }
[ForeignKey("ItemSelectListId")]
[ValidateNever]
public ItemSelectList ItemSelectList { get; set; }
}
BTBNewLien2 controller (here I added all the data binding functionalities for my dropdown):
namespace CommercialCalculatorWeb.Areas.Admin.Controllers
{
public class BTBNewLien2Controller : Controller
{
private readonly IUnitOfWork _unitOfWork;
public BTBNewLien2Controller(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public IActionResult Index()
{
IEnumerable<BTBNewLien2> objBTBNewLienList = _unitOfWork.BTBNewLien2.GetAll();
return View(objBTBNewLienList);
}
public IActionResult Create()
{
BTBNewLien2 btbNewLien2 = new();
IEnumerable<SelectListItem> BuyerSelectList = _unitOfWork.Buyer.GetAll().Select(
c => new SelectListItem
{
Text = c.Buyer,
Value = c.Id.ToString()
});
IEnumerable<SelectListItem> ItemSelectList = _unitOfWork.Item.GetAll().Select(
c => new SelectListItem
{
Text = c.Item,
Value = c.Id.ToString()
});
ViewBag.BuyerSelectList = BuyerSelectList;
ViewBag.ItemSelectList = ItemSelectList;
return View(btbNewLien2);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(BTBNewLien2 obj)
{
if (ModelState.IsValid)
{
_unitOfWork.BTBNewLien2.Add(obj);
_unitOfWork.Save();
TempData["success"] = "Row Created Successfully!";
return RedirectToAction("Index");
}
return View(obj);
}
}
}
BTBNewLien2 create view:
#model CommercialCalculator.Models.BTBNewLien2
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>BTBNewLien2</h4>
<hr />
<div class="row ml-6">
<div class="col-md-4">
<form asp-action="Create">
<div class="form-group">
<label asp-for="BuyerSelectListId" class="control-label">Buyer</label>
<select asp-for="BuyerSelectListId" asp-items="ViewBag.BuyerSelectList" class="form-control">
<option disabled selected>--Select Buyer--</option>
</select>
</div>
<div class="form-group">
<label asp-for="ItemSelectListId" class="control-label">Item</label>
<select asp-for="ItemSelectListId" asp-items="ViewBag.ItemSelectList" class="form-control">
<option disabled selected>--Select Item--</option>
</select>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
BTBNewLien2 index view:
#model IEnumerable<CommercialCalculator.Models.BTBNewLien2>
#{
ViewData["Title"] = "Index";
}
<table class="table table-bordered table-hover table-sm align-middle m-0" id="header">
<tr class="m-0" style="text-align:center;background-color: #17A2B8">
<th width="20%">
#Html.DisplayNameFor(model => model.BuyerSelectList)
</th>
<th>
#Html.DisplayNameFor(model => model.ItemSelectList)
</th>
</tr>
#foreach (var BTBNewLien2 in Model)
{
<tr class="m-0">
<td>
#Html.DisplayFor(modelItem => BTBNewLien2.BuyerSelectList)
</td>
<td>
#Html.DisplayFor(modelItem => BTBNewLien2.ItemSelectList)
</td>
</tr>
}
</table>
Try this way:
#Html.DropDownList("ItemSelectListId", new SelectList(ViewBag.ItemSelectListId, "Text", "Text"), "-- Select Item --", new { required = true, #class = "form-control" })
In my code, it works fine:
Controller:
[HttpGet]
public IActionResult Create()
{
List<SelectListItem> test = new()
{
new SelectListItem { Value = "1", Text = "test1" },
new SelectListItem { Value = "2", Text = "test2" },
new SelectListItem { Value = "3", Text = "test3" },
new SelectListItem { Value = "4", Text = "test4" }
};
ViewBag.ItemSelectListId = test;
return View();
}
[HttpPost]
public IActionResult Create(Test test)
{
return View();
}
View:
<div class="row ml-6">
<div class="col-md-4">
<form asp-action="Create">
<div class="form-group">
<label asp-for="ItemSelectListId" class="control-label">Buyer</label>
#Html.DropDownList("ItemSelectListId", new SelectList(ViewBag.ItemSelectListId, "Text", "Text"), "-- Select Item --", new { required = true, #class = "form-control" })
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
Test Result:

I am getting null value in the server side from CheckBox in asp.net MVC

When I check the box, it shows it has a false value in the server side model but in the ajax call getting values it shows null values.
In the model class:
[Display(Name = "Is Buyer")]
public bool IsBuyer { get; set; }
In the Razor Page:
<div class="row g-my-4">
<div class="col-md-10 g-pl-0">
<div class="row">
<div class="col-md-1"> </div>
<div class="col-md-7 g-pl-0 g-pr-0" id="IsBuyer">
<label>
#Html.CheckBoxFor(m=>m.IsBuyer)
#*#Html.CheckBoxFor(model => model.IsBuyer, new { id = "CheckBuyer" })*#
#*#Html.CheckBox("IsBuyer")*#
Buyer
</label>
</div>
</div>
</div>
</div>
I tried to use everything but nothing is working.
Getting data values to use ajax call
Here you can see the IsBuyer attribute is null = empty, and here on the server side it's getting false value however I have checked every check box but that's what I am getting back
Try to use usual BeginForm() block and post data like below:
#model Models.ViewModel
#using (Html.BeginForm())
{
<div class="form-group row">
<p>#Html.LabelFor(l => Model.IsBuyer) </p>
#Html.CheckBoxFor(r => Model.IsBuyer)
</div>
<input id="Button" type="submit" value="Save" />
}
In the controller code:
public IActionResult IndexTest()
{
var model = new ViewModel() { IsBuyer = true };
return View(model);
}
[HttpPost]
public IActionResult IndexTest(ViewModel data)
{
if (ModelState.IsValid)
{
// your code here...
}
return RedirectToAction("IndexTest", data);
}
// View data model class
public class ViewModel
{
[Display(Name = "Is Buyer")]
public bool IsBuyer { get; set; }
// Additional propereties is defined here...
}

Currency exchange without reloading page

So, I have web application for currency exchange. What I need is to get the result of conversion without reloading the page. In this application I get data from api. After submiting the form page starts to reload and calls HttpGet method again. I get exception because of it. Is there any way to convert currency and do not reload the page?
Model
public class ExchangeRate
{
[JsonProperty("rates")]
public Dictionary<string, double> Rates { get; set; }
[JsonProperty("base")]
public string Base { get; set; }
[JsonProperty("date")]
public DateTimeOffset Date { get; set; }
}
Controller
public class HomeController : Controller
{
[HttpGet]
public async Task<ActionResult> Index()
{
ExchangeRate curencyInfo = new ExchangeRate();
using (HttpClient client = new HttpClient())
{
curencyInfo = await client.GetFromJsonAsync<ExchangeRate>("https://api.exchangeratesapi.io/latest?base=USD");
}
return View(curencyInfo);
}
[HttpPost]
public ActionResult Index(decimal fromCurrency, decimal toCurrency, decimal fromValue)
{
var toValue = toCurrency / fromCurrency * fromValue;
decimal result = Math.Round(toValue, 2);
ViewBag.toValue = result;
return View();
}
}
View
#model WebCurrencyConverter.Models.ExchangeRate
#{
ViewData["Title"] = "Currency Converter";
}
<h1>Currency Converter</h1>
<form method="post">
<select name="fromCurrency">
#foreach (var itemFrom in Model.Rates)
{
<option value="#itemFrom.Value">#itemFrom.Key</option>
}
</select>
<input type="hidden" value="#Model.Rates" />
<select name="toCurrency">
#foreach (var itemTo in Model.Rates)
{
<option value="#itemTo.Value">#itemTo.Key</option>
}
</select>
<input type="number" name="fromValue" step="any" />
<input type="number" name="toValue" value="#ViewBag.toValue" />
<input type="submit" class="btn btn-success" value="Convert" />
</form>
I get exception because of it. Is there any way to convert currency and do not reload the page?
To avoid reloading the page,I think you could use ajax to post data.
Here is a whole working demo:
View:
#model ExchangeRate
#{
ViewData["Title"] = "Currency Converter";
}
<h1>Currency Converter</h1>
<form method="post">
<select name="fromCurrency">
#foreach (var itemFrom in Model.Rates)
{
<option value="#itemFrom.Value">#itemFrom.Key</option>
}
</select>
<input type="hidden" value="#Model.Rates" />
<select name="toCurrency">
#foreach (var itemTo in Model.Rates)
{
<option value="#itemTo.Value">#itemTo.Key</option>
}
</select>
<input type="number" name="fromValue" step="any" />
<input type="number" name="toValue" /> //change here.....
//change the type to button and add the id for button
<input type="button" class="btn btn-success" id="convert" value="Convert" />
</form>
Js in View:
#section Scripts
{
<script>
$("#convert").click(function () {
console.log($('form').serialize());
$.ajax({
url: "/Home/Index",
type: "Post",
data: $('form').serialize(),
success: function (data) {
console.log(data.result);
$('input[name="toValue"]').val(data.result);
}
})
})
</script>
}
Controller:
[HttpGet]
public async Task<ActionResult> Index()
{
ExchangeRate curencyInfo = new ExchangeRate();
curencyInfo.Rates = new Dictionary<string, double>() { };
curencyInfo.Rates.Add("US", 1);
curencyInfo.Rates.Add("Euro", 0.82);
return View(curencyInfo);
}
[HttpPost]
public JsonResult Index(decimal fromCurrency, decimal toCurrency, decimal fromValue)
{
var toValue = toCurrency / fromCurrency * fromValue;
decimal result = Math.Round(toValue, 2);
return Json(new { result = result });
}
Result:

NonFactors Paging issue following search

I am using NonFactors mvcgrid6 (https://mvc6-grid.azurewebsites.net/) in my project and Paging is breaking following a search. When selecting Page 2 for example after a search has been made the whole data set is returned and not just the searched data.
Looking for a way to persist the searched for data when using the paging. Is this possible to do with this plugin?
Controller
public IActionResult Index(IndexResidentVM searchValues)
{
var indexVm = new IndexResidentVM()
{
SearchItems = _residentService.GetAllResidents(searchValues).AsQueryable(),
Groups = _groupService.GetGroups(),
Users = _userService.GetUsers()
};
return View(indexVm);
}
Index
#using CommunityContact.Core.Enums
#using NonFactors.Mvc.Grid
#model CommunityContact.Core.ViewModels.Resident.IndexResidentVM
#{
ViewData["Title"] = "Residents";
}
<h3>Allocated Residents</h3>
<form asp-action="Index" id="indexSearchForm">
<div class="form-row">
<div class="form-group col-md-3" style="margin-top: 15px;">
<label class="col-md-3">Group: </label>
<select id="indexGroupDdl" asp-for="Group" asp-items="#Model.Groups.Select(p => new SelectListItem()
{
Value = p.Name,
Text = p.Name
})" class="form-control-sm col-md-8">
<option selected="selected" value="">Please select </option>
</select>
</div>
<div class="form-group col-md-4" style="margin-top: 15px;">
<label class="col-md-4">RAG Status:</label>
<select id="indexRagStatusDdl" asp-for="RagStatus" asp-items="Html.GetEnumSelectList<Enums.RagStatus>()" class="form-control-sm col-md-6">
<option selected="selected" value="">Please select </option>
</select>
</div>
<div class="form-group col-md-4" style="margin-top: 15px;">
<label class="col-md-4">Allocated to: </label>
<select id="indexAllocatedToDdl" asp-for="User" asp-items="#Model.Users.Select(p => new SelectListItem()
{
Value = p.Name,
Text = p.Name
})" class="form-control-sm col-md-6">
<option selected="selected" value="">Please select </option>
</select>
</div>
<div class="col-md-1" style="margin-top: 15px;">
<button id="clearSearch" class="btn-sm btn-primary clear-search" title="Clear Search"><span class="fa fa-times"></span></button>
</div>
</div>
</form>
<hr />
#(Html.Grid(Model.SearchItems)
.Build(columns =>
{
columns.Add(model => model.Id).Css("hidden-column");
columns.Add(model => model.ResidentId).Titled("Resident ID");
columns.Add(model => model.Forename1).Titled("Forename");
columns.Add(model => model.Surname).Titled("Surname");
columns.Add(model => model.Group).Titled("Group");
columns.Add(model => model.CallBackDue.HasValue ? model.CallBackDue.Value.ToShortDateString() : string.Empty).Titled("Call Back Due");
columns.Add(model => model.RagStatus).Titled("RAG Status");
columns.Add(model => model.AllocatedTo).Titled("Allocated to");
columns.Add(model => Html.ActionLink(" ", "Edit", "Resident", new { id = model.Id }, new { #class = "fa fa-edit", title = "Edit" })).Css("archive-column-width");
columns.Add(model => Html.ActionLink(" ", " ", new {}, new {#class="fa fa-archive", href ="#", onclick="return archivePrompt('"+ model.Id +"')", title ="Archive"})).Css("archive-column-width");
})
.Pageable()
.RowAttributed(model => new {#class = model.RagStatus == Enums.RagStatus.Red.ToString() ? "rag-status-red" : model.RagStatus == Enums.RagStatus.Amber.ToString() ? "rag-status-amber" : model.RagStatus == Enums.RagStatus.Green.ToString() ? "rag-status-green" : null }))
#*#Html.AjaxGrid(Url.Action("Index"))*#
#section Scripts
{
<script>
// MvcGrid
[].forEach.call(document.getElementsByClassName('mvc-grid'), function (element) {
new MvcGrid(element);
});
</script>
}
View Model
public class IndexResidentVM
{
public int Id { get; set; }
public string ResidentId { get; set; }
public string Forename1 { get; set; }
public string Surname { get; set; }
public string Group { get; set; }
public string User { get; set; }
public Enums.Enums.RagStatus RagStatus { get; set; }
public IQueryable<ResidentSearchItemVM> SearchItems { get; set; }
public IEnumerable<EditUserVM> Users { get; set; }
public IEnumerable<GroupVM> Groups { get; set; }
}
This was solved by making the call to the controller a GET request and not POST. Adding the following to my form tag fixed it for me -
method="GET"

Resources