Fairly new to ASP.NET CORE so this could be a rookie mistake but it has be baffled!
I have been working on integrating a plugin for Square with some existing code, and when I write the data to console it's there but as soon as it's passed to the view I get a nullable error.
Controller
public IActionResult AccountPayments()
{
var appId = _config.GetValue<string>("AppSettings:ApplicationId");
var locId = _config.GetValue<string>("AppSettings:LocationId");
var env = _config.GetValue<string>("AppSettings:Environment");
ModelState.Clear();
var acc = new AccountPayment();
acc.ApplicationId = appId;
acc.LocationId = locId;
acc.PaymentFormUrl = env;
Console.WriteLine(acc.LocationId + " " + locId + " " + env);
return View(acc);
}
View
#page
#model AccountPayment
#section Scripts {
<!-- link to the SqPaymentForm library -->
<script type="text/javascript" src="#Model.PaymentFormUrl"></script>
<script type="text/javascript">
window.applicationId = "#Model.ApplicationId";
window.locationId = "#Model.LocationId";
</script>
<!-- link to the local SqPaymentForm initialization -->
<script type="text/javascript" src="~/js/sq-payment-form.js"></script>
}
Model
namespace WebInvoice.Pages
{
public class AccountPayment : PageModel
{
public string PaymentFormUrl { get; set; }
public string ApplicationId { get; set; }
public string LocationId { get; set; }
}
}
When I remove the #model from the view it works OK.
When I check the console it displays the information.
When I run the application the view above returns the below error.
"System.NullReferenceException: 'Object reference not set to an instance of an object.'"
Eternally grateful to anyone who can shed some light on the issue.
If you want to return View,don't add #page in your view,#page means it's a razor page rather than razor view.And also PageModel is used in razor page.You can refer to the official doc about razor page.Here is a demo about mvc:
Model:
public class AccountPayment
{
public string PaymentFormUrl { get; set; }
public string ApplicationId { get; set; }
public string LocationId { get; set; }
}
View(AccountPayment.cshtml):
#model AccountPayment
#section Scripts {
<!-- link to the SqPaymentForm library -->
<script type="text/javascript" src="#Model.PaymentFormUrl"></script>
<script type="text/javascript">
window.applicationId = "#Model.ApplicationId";
window.locationId = "#Model.LocationId";
</script>
<!-- link to the local SqPaymentForm initialization -->
<script type="text/javascript" src="~/js/sq-payment-form.js"></script>
}
Controller:
public IActionResult AccountPayments()
{
var appId = _config.GetValue<string>("AppSettings:ApplicationId");
var locId = _config.GetValue<string>("AppSettings:LocationId");
var env = _config.GetValue<string>("AppSettings:Environment");
ModelState.Clear();
var acc = new AccountPayment();
acc.ApplicationId = appId;
acc.LocationId = locId;
acc.PaymentFormUrl = env;
Console.WriteLine(acc.LocationId + " " + locId + " " + env);
return View(acc);
}
appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"AppSettings": {
"ApplicationId": "123",
"LocationId": "456",
"Environment": "Development"
}
}
result:
Related
I want to use #AjaxExtensions.ActionLink(AjaxHelper, String, String, String, RouteValueDictionary, AjaxOptions) in cshtml file (ASP.Net 6 MVC).
#model List<Shift>
#using System.Web.Mvc.Ajax;
#{
AjaxOptions deleteOptions = new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "table"
};
}
#foreach (Shift shift in Model)
{<td>
#AjaxExtensions.ActionLink( ???,"Delete", "DeleteShift", "MainDoctor", new{id=shift.Id}, deleteOptions)
</td>
}
As this document said, AjaxExtensions.ActionLink is only applies to ASP.NET MVC 5.2, and the correct usage should be:
#Ajax.ActionLink("Delete", "DeleteShift", "MainDoctor", new { id = shift.Id }, deleteOptions)
In ASP.NET 6, you need use an alternative way like below:
<a data-ajax="true" data-ajax-mode="replace" data-ajax-update="#table" data-ajax-url="#Url.Action("DeleteShift", "MainDoctor", new { id = shift.Id})">Delete</a>
A simple working demo you could follow:
Model:
public class Test
{
public string Id{ get; set; }
}
View(Views/Home/Index.cshtml):
#model Test
<div id="table">
#Model.Id
<a data-ajax="true" data-ajax-mode="replace" data-ajax-update="#table" data-ajax-url="#Url.Action("DeleteShift", "MainDoctor", new { id = 1 })">Delete</a>
</div>
#section Scripts
{
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-ajax-unobtrusive/3.2.6/jquery.unobtrusive-ajax.js" integrity="sha256-v2nySZafnswY87um3ymbg7p9f766IQspC5oqaqZVX2c=" crossorigin="anonymous"></script>
}
Controller:
public class MainDoctorController:Controller
{
public IActionResult DeleteShift(int id)
{
var model = new Test()
{
Id = "bb"
};
return PartialView("/Views/Home/Index.cshtml", model);
}
}
public class HomeController : Controller
{
public async Task<IActionResult> Index()
{
var model = new Test()
{
Id = "aaa"
};
return View(model);
}
}
Result:
Is it OK to call a method in the #functions{} section in razor pages directly from HTML? This seems to work fine and it's much easier than calling an API, but I was wondering if there is a downside to this (security, performance, etc)?
For example, in the code...
#functions {
public class Tickets: PageModel
{
public ApplicationDbContext _db { get; set; }
public Tickets(ApplicationDbContext db)
{
_db = db;
}
public void OnGet()
{
}
public string GetTickets(int Top) //--> THIS IS THE METHOD I AM CALLING
{
var data = _db.Tickets.OrderByDescending(x => x.CreatedAt).Take(Top);
var jdata = JsonConvert.SerializeObject(data.ToList());
return jdata;
}
}
}
And the HTML...
<div class="card alert-warning" v-for="ticket in tickets">
<div class="card-body">
<h4 class="card-title">{{ticket.TicketSubject}}</h4>
Card link
Another link
</div>
</div>
#section Scripts {
<script>
new Vue({
el: '#app',
data: {
dismissSecs: 5,
dismissCountDown: 5,
tickets: #Html.Raw(Model.GetTickets(100)), //-->THIS WORKS, BUT IT IS OK TO USE LIKE THIS?
xx: ''
}
})
</script>
}
It works because I believe the method is called when the page is being rendered and you have constant value being passed in. It would not automatically do something like update client-side without AJAX code being involved.
But to answer you question I think the 'more correct' approach is to set a binding property in the OnGet and reference that client-side
public class Tickets : PageModel
{
public ApplicationDbContext _db { get; set; }
public Tickets(ApplicationDbContext db)
{
_db = db;
}
[BindProperty]
public string TicketData { get; set; }
public void OnGet()
{
TicketData = GetTickets(100);
}
public string GetTickets(int Top)
{
var data = _db.Tickets.OrderByDescending(x => x.CreatedAt).Take(Top);
var jdata = JsonConvert.SerializeObject(data.ToList());
return jdata;
}
}
I have define my routeconfig as :
routes.MapRoute(
"addcomments",
"addcomments/{urlLanguage}",
new { controller = "Home", action = "addcomments", urlLanguage = "h" }
);
and in Homecontroller :
public ActionResult addcomments(string urlLanguage)
{
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public string addcommentssave(int id, string yourName, string youremail, string website, string yourComment)
{
string message = " Thanks for sharing your comment! If your comment doesn't appear right away, please be patient as it may take a few minutes to publish or may require moderation.";
DateTime WishDateTime = DateTime.UtcNow;
string szRemoteAddr = System.Web.HttpContext.Current.Request.UserHostAddress;
Comments commit = new Comments();
commit.comdate = WishDateTime;
commit.comments = yourComment;
commit.email = youremail;
commit.Name = yourName;
commit.Website = website;
commit.IpAddress = szRemoteAddr;
commit.PostId = id;
commit.IsVisible = 0;
_session.Comment.Add(commit);
_session.SaveChanges();
//ViewBag.result= "<div class='message success'>" + message + "</div>";
// return View();
return "<div class='message success'>" + message + "</div>";
}
in addcomments view
#using (Ajax.BeginForm("addcommentssave", "home", null,
new AjaxOptions {
HttpMethod = "POST",
UpdateTargetId = "commentmessage",
OnBegin = "wait()",
OnSuccess = "success()",
LoadingElementId = "updating" },
new { id = "_commitForm" }))
{
}
but when i run it my form action become empty like
form action="" ....`
how to i solve it, help me
I created a simple test site to try and see if I could replicate your issue.
Here is my route config:
namespace Comments
{
// Note: For instructions on enabling IIS6 or IIS7 classic mode,
// visit http://go.microsoft.com/?LinkId=9394801
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
// Use LocalDB for Entity Framework by default
Database.DefaultConnectionFactory = new SqlConnectionFactory(#"Data Source=(localdb)\v11.0; Integrated Security=True; MultipleActiveResultSets=True");
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
}
}
Here is my HomeController.cs:
namespace Comments.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return RedirectToAction("AddComment");
}
[HttpGet]
public ActionResult AddComment()
{
return View();
}
[HttpPost]
public ActionResult AddComment(int id, string yourName, string youremail, string website, string yourComment)
{
return Content(String.Format("Got a comment, id = {0}, yourName = {1}, youremail = {2}, website = {3}, yourComment = {4}",
id,
yourName,
youremail,
website,
yourComment));
}
}
}
Here is my AddComment.cshtml:
#{
ViewBag.Title = "Add Comment";
}
<h2>Add Comment</h2>
#using (Ajax.BeginForm("AddComment", "Home", null, new AjaxOptions { HttpMethod = "POST", UpdateTargetId = "commentmessage", OnBegin = "wait()", OnSuccess = "success()", LoadingElementId = "updating" }, new { id = "_commitForm" }))
{
<b>Form Here</b>
}
Here is the view source:
<DOCTYPE html>
<html>
<head>
<title>Add Comment</title>
<link href="/Content/Site.css" rel="stylesheet" type="text/css" />
<script src="/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
</head>
<body>
<h2>Add Comment</h2>
<form action="/Home/AddComment" data-ajax="true" data-ajax-begin="wait()" data-ajax-loading="#updating" data-ajax-method="POST" data-ajax-mode="replace" data-ajax-success="success()" data-ajax-update="#commentmessage" id="_commitForm" method="post"> <b>Form Here</b>
</form>
</body>
</html>
So you can see the form path rendering. Try simplifying your route config (I didn't do anything special).
im building a site using MVC4 and i want to display a navigation bar at the top of my _ViewStart according to my Database.
How can i do so? can i use a contoroller ActionResult that fired once the index page is loaded?
or how can i triger it by a partial view
my current ActionResult returning partial view is:
public ActionResult NavigationBar()
{
var entities = new CakesDBEntities();
var articles = entities.Articles;
List<NavBarModel> navBarList = articles.Select(nb => new NavBarModel { Title = nb.title, Url = nb.url }).ToList();
return View(navBarList);
}
my model:
namespace SimplyCakes20131009.Models
{
public class NavBarModel
{
public string Title { get; set; }
public string Url { get; set; }
}
}
my partial view:
#model IEnumerable<SimplyCakes20131009.Models.NavBarModel>
#foreach (var bar in Model)
{
<li>
#Html.ActionLink(bar.Title, bar.Url)
</li>
}
How can i integrate the nav bar to my _ViewStart?
A better option would be to use the _Layout.cshtml. _ViewStart is just calls the _Layout.cshtml.
You probably don't need partial View here. You can use a Child Action that renders PartialView results.
In your
_Layout.cshtml :
You can have
#{ Html.RenderAction("Navigation", "Home"); }
This points to the HomeController and Navigation Action
Additional Note: Html.RenderAction better because it is much faster than the Html.Action.
It can handle large amount of HTML efficiently as it will directly send the result to the Response. Html.Action just returns a strings with the result.
Navigation Action has its Navigation View which is pretty much equivalent to what you had in your view.
Home/Navigation.cshtml :
#model IEnumerable<MvcApplication1.Controllers.NavViewModel>
#foreach (var nav in Model)
{
<li>#Html.ActionLink(nav.Title, nav.Url)</li>
}
HomeController.cs :
Note that you probably inject the DB access as dependency to support the testability.
public class HomeController : Controller
{
private readonly ICakesRepository _cakesRepository;
//additional constructor to support testability.
public HomeController(ICakesRepository cakesRepository) {
_cakesRepository = cakesRepository;
}
//this can be removed if you the above with IOC/DI wire-up
public HomeController() {
_cakesRepository = new CakesRepository();
}
[ChildActionOnly]
[HttpGet]
public ActionResult Navigation() {
var articles = _cakesRepository.GetArticles();
var navBarList = articles.Select(nb => new NavViewModel { Title = nb.Title, Url = nb.Url });
return PartialView(navBarList);
}
}
Additional supporting classes :
public class NavViewModel {
public string Title { get; set; }
public string Url { get; set; }
}
public interface ICakesRepository {
IEnumerable<Articles> GetArticles();
}
public class CakesRepository : ICakesRepository {
public IEnumerable<Articles> GetArticles() {
//call to a db
//fake db data
return new List<Articles>() {
new Articles(){Title = "Title1", Url = "http://urlone.com"},
new Articles(){Title = "Title2", Url = "http://urltwo.com"},
new Articles(){Title = "Title3", Url = "http://urlthree.com"}
};
}
}
public class Articles {
public string Title { get; set; }
public string Url { get; set; }
}
I have a web grid in a partial view. Each column has a display and edit mode. The display mode uses labels to display the data. When a user selects "Edit", the display mode is hidden and the edit mode is displayed. Everything works, except for the "selectValue:" in the DropDownListFor in column two. The DDLF displays the selectlist, but starts with the first value instead of using the selectedValue. I've tried every variation I can come up with. Any ideas? Thanks for taking a look at this.
#model ANet.Areas.IMS.Models.DVModel
#using System.Web.Helpers
#{var grid = new WebGrid(Model.DMRN);}
<div id="gridMRN" style=" padding:20px; " >
#grid.GetHtml(
tableStyle: "webgrid-table",
headerStyle: "webgrid-header",
footerStyle: "webgrid-footer",
alternatingRowStyle: "webgrid-alternating-row",
selectedRowStyle: "webgrid-selected-row",
rowStyle: "webgrid-row-style",
mode: WebGridPagerModes.All,
columns:
grid.Columns(
grid.Column("PK_ID", "MRN ID", format: #<text><span class="display-mode">#item.PK_ID</span><label id="lblPK_ID" class="edit-mode">#item.PK_ID</label><input type="hidden" name="PK_ID" id="PK_ID" value="#item.PK_ID" /><input type="hidden" name="fk_ID" id="fk_ID" value="#item.fk_ID" /> </text>),
grid.Column("fk_MFID", "MF", format: #<text><span class="display-mode"><label id="lblfk_MFID">#item.v_L_MF.MFN</label></span>#Html.DropDownListFor(m => m.fk_MFID, new SelectList(Model.L_MF, "Value", "Text", item.fk_MFID), new { #class = "edit-mode" })</text>, style: "webgrid-col1Width"),
grid.Column("MRN", "MRN", format: #<text> <span class="display-mode"><label id="lblMRN">#item.MRN</label></span><input type="text" id="MRN" value="#item.MRN" class="edit-mode" /></text>, style: "webgrid-col3Width"),
grid.Column("Action", format: #<text>
<button class="edit-MRN display-mode" >Edit</button>
<button class="save-MRN edit-mode" >Save</button>
<button class="cancel-MRN edit-mode" >Cancel</button>
</text>, style: "webgrid-col3Width" , canSort: false)))
</div>
<script type="text/javascript" >
$(function () {
$('thead tr th:nth-child(1), tbody tr td:nth-child(1)').hide();
$('.edit-mode').hide();
$('.edit-MRN, .cancel-MRN').on('click', function () {
var tr = $(this).parents('tr:first');
tr.find('.edit-mode, .display-mode').toggle();
$("#MRNAddFrm").toggle();
});
$('.save-MRN').on('click', function () {
var tr = $(this).parents('tr:first');
var PK_ID = tr.find("#PK_ID").val();
var fk_ID = tr.find("#fk_ID").val();
var fk_MFID = tr.find("#fk_MFID").val();
var MRN = tr.find("#MRN").val();
tr.find("#lblPK_ID").text(PK_ID);
tr.find("#lblfk_ID").text(fk_ID);
tr.find("#lblfk_MFID").text(fk_MFID);
tr.find("#lblMRN").text(MRN);
tr.find('.edit-mode, .display-mode').toggle();
var MRM =
{
"PK_ID": PK_ID,
"fk_ID": fk_ID,
"fk_MFID": fk_MFID,
"MRN": MRN
};
$.ajax({
url: '/IMS/EditMRN/',
datatype: 'json',
data: JSON.stringify(MRN),
type: 'POST',
contentType: 'application/json; charset=utf-8'
})
.success(function (data) {
$('#gridMRN').replaceWith(data);
});
$("#MRNAddFrm").toggle();
});
})
</script>
ViewModel
using IMSModel;
namespace ANet.Areas.IMS.Models
{
public class DVModel
{
private IMSEntities db = new IMSEntities();
public DVModel()
{
//Define default values here
this.PageSize = 10;
this.NumericPageCount = 10;
}
....
[Display(Name = "MF")]
public int fk_MFID { get; set; }
[Display(Name = "MRN")]
public Nullable<int> MRN { get; set; }
....
public SelectList L_MF { get; set; }
..... other selectlists
public IEnumerable<v_L_MF> v_L_MF { get; set; }
..... other ienumerables lists
//Sorting-related properties
public string SortBy { get; set; }
public bool SortAscending { get; set; }
public string SortExpression //requires using System.Linq.Dynamic; on the controller
{
get
{
return this.SortAscending ? this.SortBy + " asc" : this.SortBy + " desc";
}
}
//Paging-related properties
public int CurrentPageIndex { get; set; }
public int PageSize { get; set; }
public int PageCount
{
get
{
return Math.Max(this.TotalRecordCount / this.PageSize, 1);
}
}
public int TotalRecordCount { get; set; }
public int NumericPageCount { get; set; }
}
}
Method that loads the view model
private DVModel GetDVModel(int id)
{
var _viewModel = new DVModel
{
.... other lists
v_L_MF = unitOfWork.MFRepository.Get().OrderBy(o => o.MFN),
.... other lookup lists
L_MF = new SelectList(unitOfWork.MFRepository.Get().OrderBy(o => o.MFN), "PK_MFID", "MFN", String.Empty),
};
return _viewModel;
}
Your DropdownlistFor calling will the issue.
Please lets check the follwing site.
You should give the default value on dropdownlist level, and not on select list level.
I dont remember correctly the real calling but something like this should be tryied:
#Html.DropDownListFor(m => m.fk_MFID, new SelectList(Model.L_MF, "Value", "Text", item.fk_MFID), new { #class = "edit-mode" }, "Default value")