ASP MVC Button Click - asp.net-mvc

I would like to click on button and use Next method in Controller, but i dont want go to another view! I want stay here in VIEW and my property should be change. This idea doesnt work :(( How can i do it??
Its my controller
public class VisitsController : Controller
{
Terminarz terminarz = new Terminarz();
Daty data = new Daty();
public VisitsController()
{
terminarz.aktualnaData = DateTime.Now.Date;
terminarz.pierwszyDzienTyg = data.pierwszyDzienTygodnia(terminarz.aktualnaData);
terminarz.ostatniDzienTyg = data.ostatniDzienTygodnia(terminarz.aktualnaData);
}
[ActionName("index")]
public ActionResult Index()
{
ViewBag.data = terminarz.aktualnaData;
ViewBag.pierwszyDzien = terminarz.pierwszyDzienTyg.ToString("dd/MM/yyyy ");
ViewBag.ostatniDzien = terminarz.ostatniDzienTyg.ToString("dd/MM/yyyy ");
ViewBag.wtf = terminarz.pierwszyDzienTyg.AddDays(7).ToString("dd/MM/yyyy ");
return View();
}
[NonAction]
public ActionResult Next()
{
terminarz.pierwszyDzienTyg = terminarz.pierwszyDzienTyg.AddDays(7);
terminarz.ostatniDzienTyg = terminarz.ostatniDzienTyg.AddDays(-7);
return View("index");
}
}
my model
public partial class Terminarz
{
public DateTime aktualnaData { get; set; }
public DateTime pierwszyDzienTyg { get; set; }
public DateTime ostatniDzienTyg { get; set; }
public string nazwa { get; set; }
}
my view
#ViewBag.pierwszyDzien<br />
#ViewBag.ostatniDzien<br />
#ViewBag.wtf
#using (Html.BeginForm(FormMethod.Post))
{
#Html.ActionLink("dalej","Next", "Visits")
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}

By default, all public methods in a controller can be called from an HTTP request. NonAction prevents the public method from being called from your form post. Remove the NonAction attribute from the Next method, and it should execute as expected.
You may also have to update your return to match a relative path something like this:
return View("~/Views/Index.cshtml");
Your form is also not being submitted. You are using a link inside of the form. Try this:
#using (Html.BeginForm("Next", "VisitsController", FormMethod.Post))
{
<button type="submit">Next</button>
}

Related

Passing model values to views MVC 5

I am in need of how the correct way to do this.
I can not use forms authentication
A user will "login" or confirm identity based on a value
I need to walk the user through a series of pages like so
Contact/MailAddress
Contact/Phone
Contact/Email
Contact/Summary
Questionaire/Question1
Questionaire/Question2
Questionaire/Question3
Questionaire/Summary
Final/Certify
Final/Review
I plan on using Session to hold the data but I'm having trouble figuring out how to pass the values to other views and how Redirect to other pages.
Any help will do...
Lets say you have some models like this
public class ContactModel
{
public string MailAddress { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
}
public class QuestionaireModel
{
public string Question1Answer { get; set; }
public string Question2Answer { get; set; }
public string Question3Answer { get; set; }
}
public class ContactQuestionaireModel
{
public ContactModel Contact { get; set; }
public QuestionaireModel Question { get; set; }
}
and you want to persist this model from view to view and action to action. In you controller you can create 2 actions. one for your first view and one for your second
Controller
public ActionResult ContactAddress()
{
var model = new ContactQuestionaireModel();
return View(model);
}
[HttpPost]
public ActionResult ContactAddress(ContactQuestionaireModel model)
{
var currentModel = TempData["currentModel"] as ContactQuestionaireModel;
currentModel.Contact.MailAddress = model.Contact.MailAddress;
TempData["currentModel"] = currentModel;
return RedirectToAction("ContactPhone");
}
public ActionResult ContactPhone()
{
var model = TempData["currentModel"] as ContactQuestionaireModel;
return View(model);
}
[HttpPost]
public ActionResult ContactPhone(ContactQuestionaireModel model)
{
var currentModel = TempData["currentModel"] as ContactQuestionaireModel;
currentModel.Contact.Phone = model.Contact.Phone;
TempData["currentModel"] = currentModel;
return RedirectToAction("ContactEmail");
}
in the first action ContactAddress you create a new blank model and pass that in to your view ContactAddress. In that view you can set TempData["currentModel"] equal to the model you are passing in. This will stay in TempData for 1 post back to the server. You dont need to do this on the first page since it's blank anyway but i'm doing it to save time.
View ContactAddress
#model WebApplication3.Models.ContactQuestionaireModel
#{
ViewBag.Title = "Contact Address";
TempData["currentModel"] = Model; //this will be available to me in the HttpPost action
}
#using (Html.BeginForm())
{
<div class="form-group">
#Html.LabelFor(m => m.Contact.MailAddress, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Contact.MailAddress, new { #class = "form-control" })
</div>
</div>
<button type="submit">Submit</button>
}
you'll notice in the controller code that the Post Action for ContactAddress is setting a var currentModel equal to what is in TempData["currentModel"] which was set in the ContactAddress view. Before you do a redirect to the next action ContactPhone set TempData["currentModel"] back to the model you are building and use it in the next action.
You do have the option of adding the Model as a parameter to each action and passing the currentModel object like
public ActionResult ContactPhone(ContactQuestionaireModel model)
return RedirectToAction("ContactPhone", currentModel);
its up to you really. this is not a foolproof way. page refreshes and back and forward buttons could clear out everything that was entered. Storing the information in Session or actually saving the data in a database might be more optimal.
I advise against doing what you are attempting to do by logging in with session but what you are looking for is:
TempData.yourModel = new SomeModel { Data = "yourData" };
//next page
var model = (SomeModel)TempData.yourModel;
and
RedirectToAction("yourController", "yourAction");

Model property is empty

I am trying to move from webForms to Asp.net-MVC and have some problems. I am trying to figure why this is not working, I am getting this error: "Object reference not set to an instance of an object"
I have the class 'Pages':
namespace _2send.Model
{
public class Pages
{
public string PageContent { get; set; }
public string PageName { get; set; }
public int LanguageId { get; set; }
}
}
I am inserting the value to 'Pages.PageContent' property with this class:
namespace _2send.Model.Services
{
public class PagesService : IPagesService
{
public void GetFooterlinksPage()
{
DB_utilities db_util = new DB_utilities();
SqlDataReader dr;
Pages pages = new Pages();
using (dr = db_util.procSelect("[Pages_GetPageData]"))
{
if (dr.HasRows)
{
dr.Read();
pages.PageContent = (string)dr["PageContent"];
dr.Close();
}
}
}
The Controller method looks like this:
private IPagesService _pagesService;
public FooterLinksPageController(IPagesService pagesService)
{
_pagesService = pagesService;
}
public ActionResult GetFooterLinksPage()
{
_pagesService.GetFooterlinksPage();
return View();
}
I am trying to write the property in the view like this:
#model _2send.Model.Pages
<div>
#Model.PageContent;
</div>
When debugging, the method is fired and the dataReader is inserting the value to the 'PageContent' property, but I am still getting this error from the view.
Thanks!
return View();
You didn't pass a model.
You need to pass the model as a parameter to the View() method.
You need to rewrite service method to return Pages:
public Pages GetFooterlinksPage()
{
DB_utilities db_util = new DB_utilities();
Pages pages = new Pages();
using (var dr = db_util.procSelect("[Pages_GetPageData]"))
{
if (dr.HasRows)
{
dr.Read();
pages.PageContent = (string)dr["PageContent"];
return pages;
// Because you use using, you don't need to close datareader
}
}
}
And then rewrite your action method:
public ActionResult GetFooterLinksPage()
{
var viewmodel = _pagesService.GetFooterlinksPage();
return View(viewmodel);
}
You can return a model:
var viewmodel = new _2send.Model.Pages().
//here you configure your properties
return View(viewmodel);

How can use MVC DropDownlist

I have a problem with DropDownlist in MVC
I use ModelView in my application and this is my code
namespace MedicallexiconProject.ViewModel
{
public class WordViewModel
{
private readonly ICategoryService _categoryService;
public WordViewModel(ICategoryService categoryService)
{
_categoryService = categoryService;
var selectList = _categoryService.GetAllCategorysSelectList().
Select(x => new SelectListItem
{
Text = x.Name,
Value = x.ID.ToString()
}).ToList();
Categories = selectList;
}
public WordViewModel()
{
}
public string Name { get; set; }
private IList<SelectListItem> _categories;
public IList<SelectListItem> Categories
{
get
{
if (_categories == null)
{
_categories = new List<SelectListItem>();
}
return (_categories);
}
set { _categories = value; }
}
}
}
and this is my controller
[HttpGet]
public ActionResult Create()
{
var wordViewModel = new WordViewModel(_categoryService);
ViewBag.CategoryID = wordViewModel.Categories;
return View();
}
[HttpPost]
public ActionResult Create(WordViewModel wordViewModel)
{
Mapper.CreateMap<WordViewModel, Word>();
var word = new Word();
Mapper.Map(wordViewModel, word);
if (ModelState.IsValid)
{
_wordService.AddNewWord(word);
_uow.SaveChanges();
return RedirectToAction("Index");
}
return View(wordViewModel);
}
Now how can I insert dropdownlist in my View?
As AlfalfaStrange mentioned, you should not add logic in your ViewModel. That makes it ugly ! Keep your ViewModel simple POCO.
Add one more property in your ViewModel called "SelectedCategoryID" like this
public class WordViewModel
{
public int SelectedCategoryID { set;get;}
public IList<SelectListItem> Categories { set;get;}
public string Name { set;get;}
}
Initialize your Items (Categories) of your ViewModel in your GET method. Here i am calling a method called GetCategories which returns a list of categories.I can simply call the method wherever i want.
public ActionResult Create()
{
var model=new WordViewModel();
model.Categories=YourService.GetCategories();
return View(model);
}
In your strongly typed Create view , use this
#model WordViewModel
using(#Html.BeginForm())
{
#Html.DropDownFor(x=>x.SelectedCategoryID,
new SelectList(Model.Categories,"Value","Text"),"Select Category")
<input type="submit" value="Save" />
}
In your HttpPost action method , you can check for wordViewModel.SelectedCategoryID for the selected value.
[HttpPost]
public ActionResult Create(WordViewModel wordViewModel)
{
if(ModelState.IsValid)
{
//Checck for wordViewModel.SelectedCategoryID here now
}
//some validation failed. Let's reload the category data again.
wordViewModel.Categories=YourService.GetCategories();
return View(wordViewModel);
}
It's absolutely fine to include code that loads a dropdown list in your view model. A select list and a drop down are both "view" items.... they are not related to business logic and your controller and model need not know anything about SelectLists or SelectListItems or DropDownList, etc.

Issue with multiple views on single view

I have create one simple page in MVC, which is given in startup project of MVC by .net framework with slight modification in that.
I have created two models
Login
Register
Create two controllers.
LoginController
RegisterController.
Then i have use both of them to display in my home page (like facebook just an example)
Model code:
Login Model:
public class Login
{
private string email;
[Required]
public string Email
{
get { return email; }
set { email = value; }
}
private string password;
[Required]
public string Password
{
get { return password; }
set { password = value; }
}
}
Register Model
public class Register
{
private string email;
[Required]
public string Email
{
get { return email; }
set { email = value; }
}
private string password;
[Required]
public string Password
{
get { return password; }
set { password = value; }
}
private string name;
[Required]
public string Name
{
get { return name; }
set { name = value; }
}
}
View of Login and Register both is created using "Create" Option.
Both contains
<input type="submit" value="Create" />
Now, both views are on my other page, home page.
#Html.Action("Index", "Login")
#Html.Action("Index", "Register")
Both display okay, but when i click on any of the "create" button of any of the view, it also gets fire the event in controller for the other one.
My controller code....Logincontroller.
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(Login lgobj)
{
System.Threading.Thread.Sleep(2000);
string email = lgobj.Email;
string password = lgobj.Password;
return View();
}
RegisterController:
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(Register model)
{
return View();
}
Can anyone please specify the reason, or what is missing in my code?
If not clear, please let me know, i will be describe more.
Try changing your Home View to this:
#using (Html.BeginForm())
{
#Html.Action("Index", "Login")
}
#using (Html.BeginForm())
{
#Html.Action("Index", "Register")
}
What I think is happening is that your submit is calling a POST to the wrong controller, as there is no distinct difference of forms.
Ok so you have a page (a View) that displays two ActionLinks. Once clicked, these two ActionLinks brings you to the LoginController or the RegisterController (depending on the link you’ve clicked). In both cases, you end up inside the Index() ActionResult of the appropriate Controller…so far so good!
Now…once inside the Index() you simply call return View() but I don’t see any code showing that these Views are strongly typed! Try the following:
LoginController:
public ActionResult Index()
{
var model = new Login();
return View(model);
}
RegisterController:
public ActionResult Index()
{
var model = new Register();
return View(model);
}
Assuming you’ve created two strongly typed views (Index.cshtml inside the Login folder and Index.cshtml inside the Register folder) make sure each view has an appropriate form and a submit button.
Little change to what mentioned by #Shark,
We need to mention the action and controller to which indivisual form will post data, If we will not specify both the form will post to the page url.
#using (Html.BeginForm("Index","Login"))
{
#Html.Action("Index", "Login")
}
#using (Html.BeginForm("Index","Register"))
{
#Html.Action("Index", "Register")
}
In this scenario, ( as commented in my first answer)
We need to use a Dynamic view page. (More Information)
Follow following steps:
Create DynamicViewPage type:
public class DynamicViewPage : ViewPage
{
public new dynamic Model { get; private set; }
protected override void SetViewData(ViewDataDictionary viewData)
{
base.SetViewData(viewData);
Model = ViewData.Model;
}
}
Your Controller will look like
public ActionResult Account(string returnUrl)
{
LoginModel loginmodel = null;//Initialize Model;
RegistrationModel registrationModel = null ;//Initialize Model;
.
.
.
.
.
return View("Account", new
{
Login = loginmodel,
Register = registrationModel
});
your View should Inherit from
Inherits="DynamicViewPage"
Now #Model.Login will give you Loginmodel
#Model.Register will give you RegisterModel
It should work as you expected.........

How to render a model property of string type as checkbox in ASP.NET MVC

I want to display a string type as checkbox on MVC view, but returns it as string type on HTTP post. The problem is that it returns false on HTTP Post. Below is my code:
View:
#model List<Car>
foreach(var car in Model){
bool isFourWheel = false;
if(bool.TryParse(car.IsFourWheel, out isFourWheel){
#Html.CheckBox("IsFourWheel", isFourWheel); //need to be rendered as checkbox, but returns string type on HTTP POST
}
}
Model:
public class Car
{
public string IsFourWheel { get; set; } //bad naming, but it can contain any type, include boolean
}
Controller:
public ActionResult Index()
{
var cars = new List<Car>(){ new Car(){IsFourWheel = "true"},new Car(){IsFourWheel = "false"} };
return View(cars);
}
[HttpPost]
public ActionResult Index(List<Car> cars) **Problem IsFourWheel is false when true is selected **
{
return View(cars);
}
Any ideal would be very much appreciated.
You can try specifying a template name in your helper:
#Html.EditorFor(car => car.IsFourWheel, "CheckBox")
And defining the template to render the data the way you want, in either ~/Views/{YourControllerName}/EditorTemplates/CheckBox.cshtml or ~/Views/Shared/EditorTemplates/CheckBox.cshtml.
You can find a whole series of post by Brad Wilson on MVC templates here:
Brad Wilson: ASP.NET MVC 2 Templates, Part 1: Introduction
It is for MVC 2, but most concepts still apply to MVC 3 as well (save for the Razor syntax).
Update:
Actually you probably don't need a custom template for this. Try using #Html.CheckBoxFor(car => car.IsFourWheel) instead.
Update 2:
Drop the following template in ~/Views/Shared/EditorTemplates:
IsFourWheel.cshtml
#functions {
private bool IsChecked() {
if (ViewData.Model == null) return false;
return Convert.ToBoolean(ViewData.Model, System.Globalization.CultureInfo.InvariantCulture);
}
}
#Html.CheckBox("", IsChecked(), new { #class = "check-box" })
Then from your view, call it like so:
#Html.EditorFor(model => model.IsFourWheel, "IsFourWheel")
I tested it and binding works in both GET and POST scenarios.
You could alter your viewmodel like this:
public class Car
{
public string IsFourWheel { get; set; }
public bool IsFourWheelBool { get { return bool.Parse(IsFourWheel); } }
}
Your view would look like this:
#Html.EditFor(x => x.IsFourWheelBool);
I think it will be easier, if you add an Id to your model. Just like this
Model:
public class Car
{
public int CarID { get; set; }
public string IsFourWheel { get; set; }
}
View:
#model IEnumerable<Car>
foreach (var car in Model)
{
if(car.IsFourWheel == "true"){
<input type="checkbox" name="carID" value="#car.CarID" checked="checked" />
}
else
{
<input type="checkbox" name="carID" value="#car.CarID" />
}
}
Controller:
[HttpPost]
public ActionResult Index(List<int> carID)
{
//handle selected cars here
return View();
}

Resources