Model property is empty - asp.net-mvc

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);

Related

Populating complex objects from view, on post, using interfaces

I'm trying to post data from a bunch of text fields using the following:
Controller:
[HttpGet]
public ActionResult Order()
{
OrderViewModel vm = new OrderViewModel();
vm.Id = "some id";
List<IOrderItem> itemList= new List<IOrderItem>();
for (int i = 0; i <= 10; i++)
{
OrderItem x = new OrderItem();
x.ItemId = i + "";
itemList.Add(x);
}
vm.OrderItemList = itemList;
return View(vm);
}
[HttpPost]
public IActionResult Order(OrderViewModel model)
{
return View("blabla");
}
These are the models:
public class OrderViewModel : B.IOrderItemViewModel
{
private List<IOrderItem> orderItems;
public List<IOrderItem> OrderItemList
{
get { return orderItems; }
set { orderItems = value; }
}
private string orderId;
public string Id
{
get { return orderId; }
set { orderId = value; }
}
}
public class OrderItem : IOrderItem
{
private string orderItemId;
public string ItemId
{
get { return orderItemId; }
set { orderItemId = value; }
}
private string _description;
public string Description
{
get { return _description; }
set { _description = value; }
}
}
this is the view:
#model OrderViewModel
#using (Html.BeginForm("Order", "Home", FormMethod.Post))
{
#for (int i = 0; i < Model.OrderItemList.Count; i++)
{
#Html.HiddenFor(x => x.OrderItemList[i].ItemId)
#Html.TextBoxFor(x => x.OrderItemList[i].Description)
<br />
}
<input type="submit" value="submit" />
}
Here is the problem - The interfaces are in another project, let's call it B. I reference B in the project.json file for the main project, A. In B, I just defined the two interfaces the are inherited above.
If I do not use any interfaces, and I just use the objects
e.g. instead of :
List<IOrderItem> OrderItemList
I use :
List<OrderItem> OrderItemList
When I run the project, and hit the view, I see the textboxes. I fill in some data and hit submit. It goes to the controller as expected. If I put a breakpoint in the HttpPost actionresult method, and look at the model, I can see all the data I entered. Perfect.
If I use the code above, where I am inheriting from some interfaces, it does not work. The view loads, I enter in some data, I post, it hits the breakpoint, but the model is empty and it's all null.
Any ideas / help would be greatly appreciated!
You cant bind to interfaces. The process of model binding involves first initializing your model (internally the DefaultModelBinder uses Activator.CreateInstance()) , but you can't initialize an interface (how would it know which type to initialize), which is why
public List<OrderItem> OrderItemList { get; set; }
works, but
public List<IOrderItem> OrderItemList { get; set; }
wont.
This article discusses it more detail and includes a section on creating a custom Abstract Model Binder that may solve your problem.

ASP MVC Button Click

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>
}

Passing Model from One Controller to Another

I need to pass a View Model from one controller to another controller. I used the below statement.
return RedirectToAction("FillNewSession", "Account", new { LoginResult = loginResult });
LoginResult is an object of the model "UserLoginProperties". FillNewSession controller is below.
public ActionResult FillNewSession(UserLoginProperties LoginResult)
{
Session["UserID"] = LoginResult.UserID.ToString();
Session["LoginID"] = LoginResult.LoginID;
Session["UserFullName"] = LoginResult.UserFullName;
Session["UserTypeID"] = LoginResult.UserTypeID;
Session["UserRefNo"] = LoginResult.UserRefNo;
Session["UserNRIC"] = LoginResult.UserNRIC;
return Redirect("~/index.aspx");
}
Problem is when "FillNewSession" controller is executed the passed parameter "LoginResult" is null.
Please Help.
If you want to pass an object through a redirect call you need to send all the properties of the object one by one, as illustrated below. You can't just pass the object as it is.
public class UserLoginProperties
{
public string UserID { get; set; }
public string LoginID { get; set; }
}
public class HomeController : Controller
{
public ActionResult Index()
{
var prop = new UserLoginProperties(){ LoginID = "123", UserID = "abc"};
return RedirectToAction("OtherAction", new { UserID=prop.UserID, LoginID=prop.LoginID });
}
public ActionResult OtherAction(UserLoginProperties prop)
{
// do whatever you want with it here
}
}

Cant pass data from one method to another in same controller

I am developing MVC application.
I am trying to pass the data from one method to another method in same controller.
But data doesn't pass properly...
Please check below code... I am trying to pass the Product list from Create to Save data method.
namespace StockWatchScreen.Controllers
{
public class OrderController : Controller
{
public class OrderProduct
{
public string SectionCode { get; set; }
public double Size { get; set; }
public double Thickness { get; set; }
public double Length { get; set; }
public double Quantity { get; set; }
}
public ActionResult Create()
{
List<OrderProduct> oProductList = new List<OrderProduct>();
OrderProduct oProduct = new OrderProduct();
oProduct.SectionCode = "123";
oProduct.Length = "123";
oProduct.Size = "123";
oProduct.Thickness = "123";
oProduct.Quantity = "123";
oProductList.Add(oProduct);
}
return RedirectToAction("SaveData", oProductList);
}
public ActionResult SaveData(List<OrderProduct> oProductList)
{
ViewBag.ProductList = oProductList;
ViewBag.OrderNo = "12321#";
return View();
}
}
}
}
In SaveData method, oProductList list shows always null.
What is reason ?
You need to return :return SaveData( oProductList); .You don't need to return RedirectToAction , and try to avoid using TempData["oProduct"] using TempData in mvc is not good practice.
Using AjaxBeginForm you on succes you can get result return SaveData( oProductList);and put it where you want .also you can use UpdateTargetId.
You can't send model like this in RedirectToAction, you should use tempdata for this communicating between actions like this
public ActionResult Create()
{
List<OrderProduct> oProductList = new List<OrderProduct>();
OrderProduct oProduct = new OrderProduct();
oProduct.SectionCode = "123";
oProduct.Length = "123";
oProduct.Size = "123";
oProduct.Thickness = "123";
oProduct.Quantity = "123";
oProductList.Add(oProduct);
}
TempData["oProduct"] = oProductList;
return RedirectToAction("SaveData");
}
And in the recieving controller
public ActionResult SaveData(List<OrderProduct> oProductList)
{
ViewBag.ProductList = TempData["oProduct"] as List<OrderProduct> ;
ViewBag.OrderNo = "12321#";
return View();
}
This is because RedirectToAction is doing a 301 redirection, and it is actually the client initiating a Get request to the /SaveData action.

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.

Resources