Multiple forms on MVC view - asp.net-mvc-4

I have what I hope is a simple question. I am trying to use multiple forms on an MVC view (like at Multiple Forms in same page ASP.net MVC) - each calling different actions on the same controller. My issue is that any form where I call an action that is named different from the view I get an error. Simple example below:
Index.cshtml
#using (Html.BeginForm("index", null, FormMethod.Post, new { #class = "form -horizontal" }))
{
<button class="btn btn-primary" type="submit">index</button>
}
<br />
#using (Html.BeginForm("foobar", null, FormMethod.Post, new { #class = "form -horizontal" }))
{
<button class="btn btn-primary" type="submit">foobar</button>
}
testController
public class testController : Controller
{
// GET: test
public ActionResult Index()
{
return View();
}
[HttpPost, ActionName("Index")]
public ActionResult IndexPost()
{
return View();
}
[HttpPost]
public ActionResult foobar()
{
return View();
}
Clicking the "index" button works (does nothing)
Clicking the "foobar" button throws an error
The view 'foobar' or its master was not found or no view engine supports the searched locations.
I am obviously missing something - any wisdom is appreciated

I hope this would help:
[HttpPost, ActionName("Index")]
public ActionResult IndexPost()
{
return View("Index");
}
[HttpPost]
public ActionResult foobar()
{
return View("Index");
}

Related

How to properly refresh a PartialView in Razer page .Net Core 3.1

I have a simple page that also includes a PartialView so that I can refresh the data every 10 seconds returned by the PartialView. It really is a trivial task but I'm not proficient enough with the whole web part and especially JavaScript.
How can I run the LoadData() Method every X seconds so that my partialView shows the data?
I have found the following JS code which I think should be able to refresh the PartialView but I don't know how to adapt this to my situation:
<script type="text/javascript">
$(function () {
setInterval(loadTable, 1000); // invoke load every second
loadTable(); // load on initial page loaded
});
function loadTable() {
$('#data').load('/controller/tabledata');
}
</script>
My index.cshtml looks like this:
#page
#model IndexModel
<div class="data">
<partial name="~/Pages/Shared/_BezoekersData.cshtml" />
</div>
The indexModel:
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.SharePoint.Client;
using PnP.Framework;
using System.Security;
namespace MyNameSpace.Pages
{
public class IndexModel : PageModel
{
public IActionResult OnGetPartial() => Partial("\\Shared\\_BezoekersData.cshtml");
// properties left out for clarity
public void OnGet()
{
LoadData();
}
public void LoadData()
{
// dataRetrieval part here.
}
}
}
_BezoekersData.cshtml:
#{
ViewData["Title"] = "Home page";
}
<div style="position:fixed; left:65px; top:25px; color:#c2a149; font-size:75px; ">#Model.Vestiging</div>
<div style="position:fixed; left:1100px; top:180px; color:#c2a149; font-size:50px">#Model.MaxAantal</div>
<div style="position:fixed; left:1100px; top:285px; color:#c2a149; font-size:50px">#Model.HuidigAantal</div>
You should add one more function to call the partial view and refresh it, check this:
public void OnGet()
{
LoadData();
}
public void LoadData()
{
MyModel=new MyModel {thetime=DateTime.Now };
}
public PartialViewResult OnGetMyPartial() // extra method to get data
{
MyModel = new MyModel { thetime = DateTime.Now };
return Partial("_BezoekersData", MyModel);
}
View:
Mind it must be ** div id="data"**, because you use #data to call jquery function.
Pass model data to partial, add model attribute.
And to call the new method, using handler:
In main view: #Model.MyModel.thetime
<div id="data">
<partial name="~/Pages/Shared/_BezoekersData.cshtml" model="Model.MyModel"/> //add a model attribute
</div>
#section Scripts
{
<script type="text/javascript">
$(function () {
setInterval(loadTable, 1000);
loadTable();
});
function loadTable() {
$('#data').load("/Index?handler=MyPartial"); //handler to call razor method
}
</script>
}
This is the partial view:
#model He621.Models.MyModel
In partial:<div style="position:fixed; left:65px; top:100px; color:#c2a149; font-size:75px; ">#Model.thetime</div>
Result:
The time refreshes every 1 seconds, and will only refresh the partial:

Refer to hidden type ID in controller page

I need to use hdNoOfColumns and hdNoOfRows in a controller page which are defined as hidden type in View page. I am getting a "context does not exist" error. How do refer to a hidden type ID in the controller page?
View:
<input id="hdNoOfRows" type="hidden" name="hdNoOfRows" />
<input id="hdNoOfColumns" type="hidden" name="hdNoOfColumns"/>
Controller:
hdNoOfColumns.Value = count.ToString();
dsCount = ds.Tables[0].Rows.Count;
hdNoOfRows.Value = dsCount.ToString();
seatCount = dsS.Tables[0].Rows.Count;
asp.net mvc does not work as asp.net web forms, you need to create a model and then use it:
First Create a Model:
public class TableModel
{
public string NoOfColumns { get; set;}
public string NoOfRows { get;set; }
}
Now in your controller action:
public class BarController : Controller
{
public ActionResult Foo()
{
TableModel model = new TableModel();
model.NoOfColumns= count.ToString();
dsCount = ds.Tables[0].Rows.Count;
model.NoOfRows= dsCount.ToString();
seatCount = dsS.Tables[0].Rows.Count;
return View(model);
}
}
Now in your View use HiddenFor() :
#model TableModel
#Html.HiddenFor(x=>x.NoOfColumns)
#Html.HiddenFor(x=>x.NoOfRows)
post them by putting them inside form :
and For posting back values to controller you will have to put them in a form:
#model TableModel
#using(Html.BeginForm("Foo", "Bar", FormMethod.Post))
{
<input id="hdNoOfRows" type="hidden" name="hdNoOfRows" />
<input id="hdNoOfColumns" type="hidden" name="hdNoOfColumns"/>
<input type="submit" value="Post"/>
}
and then in your controller controller handle in post action of it:
public class BarController : Controller
{
public ActionResult Foo()
{
TableModel model = new TableModel();
model.NoOfColumns= count.ToString();
dsCount = ds.Tables[0].Rows.Count;
model.NoOfRows= dsCount.ToString();
seatCount = dsS.Tables[0].Rows.Count;
return View(model);
}
[HttpPost]
public ActionResult Foo(TableModel model)
{
// do saving in db or whatever business logic
return View(model);
}
}

Paramete value is null in one action method and non-null in another

I have controller called Documents with three action methods:
public ActionResult Save(string returnUrl){
TempData["returnUrl"]=returnUrl;
return View(viewName: "Save");
}
[HttpPost]
public ActionResult Save(string returnUrl){
return Redirect(returnUrl);
}
and
[HttpPost]
public ActionResult Cancel(string returnUrl){
return Redirect(returnUrl);
}
And here's the content of the Save.cshtml view:
#Html.Hidden(TempData["returnUrl"].ToString())
#using (Html.BeginForm){
<!--Some html here-->
<input type="submit" value="Save"/>
}
#using (Html.BeginForm(actionName:"Cancel",controllerName:"Documents")){
<input type="submit" value="Cancel"/>
}
Of course, the above code does not reflect what I need to do in real world but one problem made me strip my code down to this simplest stage. The problem is that the returnUrl argument is null when I call the Cancel action method. Why is that?
In order to post back to FormCollection, inputs associated with the form need to be located inside the <form> tag (except if using the form attribute). In your case where you have 2 forms and need to post back the value of returnUrl, you would need 2 inputs. This will create elements with duplicate id's if using html helpers. A better approach would be to include the value in the form element, for example
Controller
[HttpGet]
public ActionResult Save(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View("Save");
}
[HttpPost]
public ActionResult Save(string returnUrl, MyModel, model)
{
....
}
[HttpPost]
public ActionResult Cancel(string returnUrl, MyModel, model)
{
....
}
View
#using (Html.BeginForm("Save", "Documents", new { ReturnUrl = ViewBag.ReturnUrl })) {
....
#using (Html.BeginForm("Cancel", "Documents", new { ReturnUrl = ViewBag.ReturnUrl })) {
....

Why submit button does't call controller function?

I have a small problem with calling controller function. Strange is that every other submit button works fine. But this one has problem which I cannot solve for now.
I will show you two forms with submit buttons becouse there is only one working fine.
Controller:
public class MyController : Controller
{
public ActionResult MethodOne()
{
...
return RedirectToAction("index");
}
public ActionResult MethodTwo()
{
...
return RedirectToAction("index");
}
}
And the view:
//This one works fine!!
#using (Html.BeginForm("MethodOne", "My", FormMethod.Post))
{
<input id="Some-cool-id" type="submit" value="Add!" />
}
//This one doesn't work?!
#using (Html.BeginForm("MethodTwo", "My", FormMethod.Post))
{
<input id="some-cool-id2" type="submit" value="Delete"!" />
}
Error is telling that Method2 is not in the required path.
Resource not found.
Description: HTTP 404. Searched resource (or ...) ...
Required path URL: /My/MethodTwo
I was searching what is bad but in the end, I need a help, thanks.
Add the property [HttpPost] before the method.
Try this,
#using (Html.BeginForm("MethodTwo", "Test", FormMethod.Post))
{
<input type="submit" value="asd" />
}
#using (Html.BeginForm("MethodOne", "Test", FormMethod.Post))
{
<input type="submit" value="poll" />
}
Controller
public class TestController : Controller
{
public ActionResult MethodOne()
{
return RedirectToAction("CustomerInfo");
}
public ActionResult MethodTwo()
{
return RedirectToAction("CustomerInfo");
}
[HttpGet]
public ActionResult CustomerInfo()
{
ViewBag.CustomerNameID = new SelectList(List, "CustomerId", "customerName");
ViewBag.RegisterItems = GetAllRegisterData();
ViewData["SampleList"] = GetAllRegisterData();
return View();
}
}

Creating dropdownlist from values in database

I have a table called Roles with three fields
Guid RoleId
string RoleName
string Description
In my register.cshtml view I want to have a dropdownlist which shows the list of RoleName from Roles table. I also need to be able to get that value and work with it, like assigning the Role to user, which will in done in controller.
My view currently looks like the one below, i'm using model as AspNetUser but it doesn't have knowledge about Role which is what I want to show in dropdownlist.
#model Sorama.CustomAuthentiaction.Models.AspNetUser
#{
ViewBag.Title = "Register";
Layout = "~/Views/shared/_BootstrapLayout.empty.cshtml";
}
#section Styles{
<link href="#Url.Content("~/Content/bootstrap.css")" rel="stylesheet" type="text/css" />
}
<div class ="form-signin">
#using (Html.BeginForm("Register", "Account"))
{
#Html.ValidationSummary(true)
<h2 class="form-signin-heading"> Register </h2>
<div class ="input-block-level">#Html.TextBoxFor(model=>model.Email, new{#placeholder = "Email"})</div>
<div class ="input-block-level">#Html.TextBoxFor(model=>model.UserName, new{#placeholder = "UserName"})</div>
<div class ="input-block-level">#Html.PasswordFor(model=>model.Password, new{#placeholder ="Password"})</div>
<div class ="input-block-level">#Html.DropDownListFor(//don't know what to do
<button class="btn btn-large btn-primary" type="submit">Register</button>
}
</div>
My controller looks like this
public class AccountController : Controller
{
//private readonly IDbContext dbContext;
//
// GET: /Account/
[HttpGet]
public ActionResult Login()
{
return View();
}
[HttpPost]
[AllowAnonymous]
public ActionResult Login(LoginModel model)
{
if(Membership.ValidateUser(model.UserName, model.Password))
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
return RedirectToAction("Index", "Home");
}
ModelState.AddModelError("", "The user name or password provided is incorrect.");
return View(model);
}
[HttpGet]
public ActionResult Register()
{
string [] roles = Roles.GetAllRoles();
return View(roles);
}
[HttpPost]
public ActionResult Register(AspNetUser model)
{
return View();
}
public ActionResult Index()
{
return View();
}
}
What do I need to do, to have that dropdownlist?
In your controller you need to pass the string[] (IEnumerable<string>) representing your roles into your view somehow...
There are many ways to achieve this, but in your AccountController you could do the following:
public class AccountController : Controller
{
private IDbContext dbContext;
public AccountController(IDbContext dbContext)
{
// Made up field that defines your GetAllRoles method
this.dbContext = dbContext;
}
public ActionResult Register()
{
// Call the GetAllRoles() and capture the result in a variable called roles
var roles = dbContext.GetAllRoles();
return View(new AspNetUser {
Roles = roles
});
}
}
Note: I do not enforce the list to be in any form in the controller (I do not specify it should be a select list), I may want to display the items as in a different way and I let the view be flexible by passing the values only and allowing the view to decide how to render the values.
In your View you can then use where you want the dropdown list to appear:
#Html.DropDownListFor(model => model.Roles, Model.Roles
.Select(role => new SelectListItem { Text = role, Value = role })
As I mentioned, there are many ways to achieve what you are wanting but almost one thing is certain, that with aspnet mvc you will most likely be using the Html helper DropDownListFor MSDN Documentation here:
http://msdn.microsoft.com/en-us/library/system.web.mvc.html.selectextensions.dropdownlistfor(v=vs.108).aspx
EDIT 1:
Create a model to hold the User and Role informations like so:
public class RegisterViewModel
{
public AspNetUser AspNetUser { get; set; }
public IEnumerable<string> Roles { get; set; }
}
In the controller it could look like so:
public class AccountController : Controller
{
private RoleProvider roleProvider;
public AccountController(RoleProvider roleProvider)
{
this.roleProvider = roleProvider;
}
public ActionResult Register()
{
// Call the GetAllRoles() and capture the result in a variable called roles
// var roles = roleProvider.GetAllRoles();
// Or, as you have specified:
var roles = Roles.GetAllRoles();
return View(new RegisterViewModel {
AspNetUser = GetTheAspNetUser(),
Roles = roles
});
}
}
In the View you need to update the model to use:
#model Sorama.CustomAuthentiaction.Models.RegisterViewModel
If you are unwilling/unable to make such a change you could add the list of Roles to the Viewbag:
ViewBag.RoleList = roleProvider.GetAllRoles();
Or as you alluded to:
ViewBag.RoleList = Roles.GetAllRoles();
Then access in the View like so:
#Html.DropDownListFor(model => model.Roles, ViewBag.RoleList
.Select(role => new SelectListItem { Text = role, Value = role })
In a similar scenario, I've done something like this:
private void BagSelectList()
{
ViewBag.List = new SelectList(
db.SetOfCandidateValues,
"KeyPropertyOfTheSet",
"NameOfThePropertyToAppearInTheDropDownList",
selectedValue);
}
And in the view:
#Html.DropDownListFor(
model => model.ForeignKeyProperty,
(SelectList)ViewBag.List)
(Of course, if you dislike the ViewBag, you can do it using the strongly typed view model.)