two models in a view - not working for me - asp.net-mvc

I have created an entity data model from my database. however in certain areas of the application i need to pass two models. thus i create a third model which has as properties the objects of each required model.
In the scenario, i want to use one model just to show some data to the user and the other is to be populated by the user using form elements. therefore, i create a constructor in my custom model to populate it. here's the code:
THE CUSTOM MODEL
public class ordersModel
{
public ordersModel(order or)
{
this.prods = new order_products();
this.new_order = new order();
this.new_order.customer_id = or.customer_id;
this.new_order.my_id = or.my_id;
this.new_order.my_order_id = or.my_order_id;
this.new_order.order_date = or.order_date;
this.new_order.order_status_id = or.order_status_id;
}
public order new_order { get; set; }
public order_products prods { get; set; }
}
IT IS USED IN THE CONTROLLER AS FOLLOWS:
public ActionResult Create()
{
order or = new order();
// Store logged-in user's company id in Session
//or.my_id = Session["my_id"].ToString();
//do something to allow user to select customer, maybe use ajax
or.customer_id = "123";
or.order_amount = 0;
or.my_id = "74973f59-1f6c-4f4c-b013-809fa607cad5";
// display date picker to select date
or.order_date = DateTime.Now.Date;
// fetch statuses from database and show in select list box
or.order_status_id = 1;
return View(or);
}
//
// POST: /Orders/Create
[HttpPost]
public ActionResult Create(order or)
{
using (invoicrEntities db = new invoicrEntities())
{
var temp = db.last_order_number.SingleOrDefault(p => p.my_id == or.my_id);
if (temp != null)
{
or.my_order_id = temp.my_order_id + 1;
if (ModelState.IsValid)
{
ordersModel ord = new ordersModel(or);
db.orders.AddObject(or);
temp.my_order_id = temp.my_order_id + 1;
//TempData["my_order_id"] = or.my_order_id;
db.SaveChanges();
return RedirectToAction("AddProducts", ord);
//return RedirectToAction("AddProducts", new { id = or.my_order_id });
}
return View(or);
}
return RedirectToAction("someErrorPageDueToCreateOrder");
}
}
public ActionResult AddProducts()
{
using (invoicrEntities db = new invoicrEntities())
{
//string my_id = TempData["my_id"].ToString();
//string my_order_id = TempData["my_order_id"].ToString();
string my_id = "74973f59-1f6c-4f4c-b013-809fa607cad5";
int my_order_id = 1;
//Int64 my_order_id = Convert.ToInt64(RouteData.Values["order_id"]);
// Display this list in the view
var prods = db.order_products.Where(p => p.my_id == my_id).Where(p => p.my_order_id == my_order_id).ToList();
var or = db.orders.Where(p => p.my_id == my_id).Where(p => p.my_order_id == my_order_id).ToList();
if (or.Count == 1)
{
//ViewData["name"] = "sameer";
ViewData["products_in_list"] = prods;
ViewData["order"] = or[0];
return View();
}
return RedirectToAction("someErrorPageDueToAddProducts");
}
}
[HttpPost]
public ActionResult AddProducts(order_products prod)
{
prod.my_id = "74973f59-1f6c-4f4c-b013-809fa607cad5";
// find a way to get the my_order_id
prod.my_order_id = 1;
return View();
}
THIS ALL WORKS OUT WELL, UNTIL IN THE "ADDPRODUCTS" VIEW:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<invoicr.Models.ordersModel>" %>
AddProducts
<h2>AddProducts</h2>
<%: Model.new_order.my_id %>
the above statement gives an error
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
what am i doing wrong here?

You seem to be passing the wrong model when redisplaying your Create view.
Try passing the ord instance which is of type ordersModel and which is what your view is strongly typed to:
public ActionResult Create(order or)
{
using (invoicrEntities db = new invoicrEntities())
{
var temp = db.last_order_number.SingleOrDefault(p => p.my_id == or.my_id);
if (temp != null)
{
or.my_order_id = temp.my_order_id + 1;
ordersModel ord = new ordersModel(or);
if (ModelState.IsValid)
{
db.orders.AddObject(or);
temp.my_order_id = temp.my_order_id + 1;
db.SaveChanges();
return RedirectToAction("AddProducts", ord);
}
return View(ord);
}
return RedirectToAction("someErrorPageDueToCreateOrder");
}
}
UPDATE:
Now that you have shown your AddProducts action you are not passing any model to the view although your view expects an ordersModel instance. So don't just return View();. You need to pass an instance of ordersModel:
if (or.Count == 1)
{
ViewData["products_in_list"] = prods;
ViewData["order"] = or[0];
ordersModel ord = new ordersModel(or[0]);
return View(ord);
}

Related

Display ads on multiple Views by using single controller method in MVC

I want to display different ads on multiple Views from single method. Currently, I have created separate controller method for the ads and then passing page name by using session from each View's controller method. I want to get rid off any code related to ads from each controller method.
Please suggest me way to do this.
Home controller
public ActionResult Index()
{
ClsHomeContent model = new ClsHomeContent();
List<Advertisement> advertList = new List<Advertisement>();
var context = new ApplicationDbContext();
var advert = context.Advertisement.ToList();
var pageName = context.Advertisement.Where(x => x.Page == "Home").Select(y => y.Page).FirstOrDefault();
Session["PageName"] = pageName;
return View(model);
}
HorseTracker Controller
public ActionResult HorseTracker()
{
List<Advertisement> advertList = new List<Advertisement>();
var advert = context.Advertisement.ToList();
var pageName = context.Advertisement.Where(x => x.Page == "HorseTracker").Select(y => y.Page).FirstOrDefault();
Session["PageName"] = pageName;
return View(model);
}
Then using this session value
public ClsAdvertisment advertPosition()
{
List<Advertisement> advertList = new List<Advertisement>();
ClsAdvertisment model = new ClsAdvertisment();
var context = new ApplicationDbContext();
var advert = context.Advertisement.ToList();
foreach (var advertisementData in advert)
{
if (advertisementData.Position == Session["PageName"] + "_Top_Left" || advertisementData.Position == Session["PageName"] + "_Top_Right" || advertisementData.Position == Session["PageName"] + "_Middle" || advertisementData.Position == Session["PageName"] + "_Left")
{
advertList.Add(new Advertisement()
{
AdvertId = advertisementData.AdvertId,
Position = advertisementData.Position,
FilePath = advertisementData.FilePath,
Hemisphere = advertisementData.Hemisphere,
Link = advertisementData.Link,
Title = advertisementData.Title
});
}
}
model.advertisement = advertList;
return model;
}
[ChildActionOnly]
public PartialViewResult Advertisement()
{
var model= advertPosition();
return PartialView("_pAdvertisement", model);
}
Created separate partial view
foreach (var item in Model.advertisement)
{
if (#item.Hemisphere == 1 && item.Position == (string)Session["PageName"]+"_Top_Left")
{
<a href="#item.Link" title="#item.Title" target="_blank">
#Html.Image(item.FilePath, "Image", "", "")
</a>
}
}
You can get the name of the parent controller and action methods in the child method using the ParentActionViewContext property of ControllerContext
[ChildActionOnly]
public PartialViewResult Advertisement()
{
ViewContext context = ControllerContext.ParentActionViewContext;
string controllerName = context.RouteData.Values["controller"].ToString();
string actionName = context.RouteData.Values["action"].ToString();
ClsAdvertisment model = advertPosition(controllerName, actionName);
return PartialView("_pAdvertisement", model);
}
Then modify your advertPosition() to
public ClsAdvertisment advertPosition(string controllerName, string actionName)
and within that method, select the ads to be displayed based on those values, and there is also no need to use Session.

ASP.NET MVC - Check for duplicate in country name without using Model Annotation

I have a ViewModel and Repository that are being used by the Controller Action for Create
Repository
BackendEntities entity = new BackendEntities();
public void AddCountry(CountriesViewModel countryModel)
{
COUNTRIES2 newCountry = new COUNTRIES2()
{
COUNTRY_ID = countryModel.COUNTRY_ID,
COUNTRY_CODE = countryModel.COUNTRY_CODE,
COUNTRY_NAME = countryModel.COUNTRY_NAME,
ACTION_STATUS = countryModel.ACTION_STATUS,
CREATED_BY = countryModel.CREATED_BY,
CREATED_DATE = countryModel.CREATED_DATE
};
entity.COUNTRIES.Add(newCountry);
entity.SaveChanges();
}
Then, I call the Repository from the Controller Action for Create.
Controller
public ActionResult Create(FormCollection collection, CountriesViewModel countries)
{
CountriesRepository countryRepo = new CountriesRepository();
if (ModelState.IsValid)
{
try
{
// TODO: Add update logic here
countryRepo.AddCountry(countries);
//countryRepo.
var notif = new UINotificationViewModel()
{
notif_message = "Record saved successfully",
notif_type = NotificationType.SUCCESS,
};
TempData["notif"] = notif;
return RedirectToAction("Index");
}
catch (Exception e)
{
this.AddNotification("Country cannot be added.<br/> Kindly verify the data.", NotificationType.ERROR);
}
}
return View(countries);
}
Please how do I Validate for duplicate COUNTRY_NAME using the condition, where ACTION_STATUS is not equal to 2
I don't want to do it from Model or View, but in the Controller or Repository.
Probably putting it before countryRepo.AddCountry(countries) in the Controller.
Create a Method In your Country Repository
public bool IsNameExist(string name, int id)
{
var result =entity.COUNTRIES.Any(c => c.COUNTRY_NAME == name && c.ACTION_STATUS != 2 && && c.COUNTRY_ID != id);
return result;
}
Then In your controller
public ActionResult Create(FormCollection collection, CountriesViewModel countries)
{
.......
if (countryRepo.IsNameExist(countries.COUNTRY_NAME, countries.COUNTRY_ID))
{
ModelState.AddModelError("COUNTRY_NAME", "COUNTRY NAME already exist.");
}
........
}

The neat and simple way for multiple models in a view

What can be simplest way for having rendered in a view information from multiple models. I use ViewModel in some scenarios (in particular when models are not related directly), but now I want to made a kind of dashboard for the current user. So apart from AspNetUsers model I have for example several models (e.g. Orders, OperationJournal, Jobs etc.) that in terms of entity have each a foreign key on UserID.
I made a ViewModel such:
namespace JobShop.Models
{
class QuickProfileVM
{
public IEnumerable<Jobs> Jobs { get; set; }
public IEnumerable<AspNetUsers> AspNetUsers { get; set; }
public IEnumerable<CreditJournal> CreditJournal { get; set; }
public IEnumerable<CandidateReview> CandidateReview { get; set; }
}
}
(since the base models that I need, are done by EF they have all about relations between entities) but it seems to me that is not enough. I am not able to view both the current user profile (so one record) and it's details (more than one record and more than one model).
I have try with Partial View, both with own controller or with actions in Dashboard View controller.
As an example an ActionResult that now I play with:
public ActionResult QuickProfile()
{
var QuickProfile = new QuickProfileVM();
var AspNetUsers = new AspNetUsers();
if (User.Identity.IsAuthenticated)
{
var CurrentUser = User.Identity.GetUserId();//UserManager.FindById(User.Identity.GetUserId());
var TheUser = db.AspNetUsers.Where(u => u.Id == CurrentUser)
.Select(u => new
{
ID = u.Id,
Email = u.Email,
PhoneNumber = u.PhoneNumber,
Companyname = u.Companyname,
Address = u.Address,
ZIP = u.ZIP,
City = u.City,
Country = u.Country,
Website = u.Website,
Facebook = u.Facebook,
Twitter = u.Twitter,
GooglePlus = u.GooglePlus,
Dribble = u.Dribble,
BirthDate = u.BirthDate,
Username = u.UserName,
Surrname = u.Surname,
Name = u.Name,
Role = u.Role,
ThumbURL = u.ThumbURL,
CreditBalance = u.CreditBalance
}).Single();
var TheJournal = db.CreditJournal.Where(tj => tj.UseBy == CurrentUser)
.Select(tj => new
{
IdJournal = tj.IdJournal,
Operation = tj.Operation,
CvID = tj.CvID,
JobID = tj.JobID,
CreditConsumed = tj.CreditConsumed,
UseDate = tj.UseDate,
UseBy = tj.UseBy
}).ToList();
//similar for Jobs and CandidateReview
//
var UserId = TheUser.ID;
var username = TheUser.Username;
var role = TheUser.Role;
var InitialCredit = TheUser.CreditBalance;
AspNetUsers.UserName = TheUser.Username;
AspNetUsers.Companyname = TheUser.Companyname;
AspNetUsers.Surname = TheUser.Surrname;
AspNetUsers.Name = TheUser.Name;
AspNetUsers.ThumbURL = TheUser.ThumbURL;
AspNetUsers.CreditBalance = InitialCredit;
//I put this to ilustrates what I have accesible for example
//about CreditJournal: only methods, not properties
QuickProfile.CreditJournal.AsEnumerable();
var id = CurrentUser;
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
AspNetUsers aspNetUsers = db.AspNetUsers.Find(id);
if (aspNetUsers == null)
{
return HttpNotFound();
}
}
return View(AspNetUsers);
//Disbled since at this stage is not usefull
//return View(QuickProfile);
//return View();
}
I suggest you consider using Html.RenderAction in your view. For example, say your main dashboard is this:
#{
ViewBag.Title = "title";
}
<h2>Multiple Models</h2>
#{ Html.RenderAction("GetData", "Foo"); }
You can use Html.RenderAction to call FooController.GetData()
public class FooController : Controller
{
public ActionResult GetData()
{
var viewModel = new FooViewModel();
viewModel.TimeStamp = DateTime.UtcNow;
return View(viewModel);
}
}
So rather than having one viewmodel with lots of other viewmodels attached as properties, you can split up the rendering of the dashboard view.
Overall this should makes things easier for you - I've used this approach in the past and have found it reduces complexity.

Passing query data from controller to view

I have been stuck on this problem for too long and would love some help.
On a view people can select two items from two radiobutton lists which returns via a FormMethod.Get to the Index event in HomeController.
These 2 values, 'parts and 'use' are queried to return a result and its passed back to the view via a viewbag. However the viewbag returns a line like { Item = Kona, Price = 400.0000, Quantity = 2 } in the view.
Whereas I want to return each item such as item.Item, Item.Price so I can use them individually.
I have tried everything I can find to no avail.
Anonymous classes items also throw red errors
View
foreach(var item in ViewBag.getstock)
{ //Show it and then make a new line with the <BR/>
#item < br / >
//{ Item = Kona, Price = 400.0000, Quantity = 2 }
}
HomeController
public ActionResult Index()
{
//this returns the entire query string
ViewBag.querystring = Request.QueryString;
//if any keys are in the url from the view
if (Request.QueryString.HasKeys())
{
//extract them out so that you can use them
//key = the name such as Part or Use it goes Key & Value this is passed to a Viewbag
//get(o) is getting the value at place 0, the first value in the url
ViewBag.querystringvalue0 = Request.QueryString.Get(0);
ViewBag.querystringvalue1 = Request.QueryString.Get(1);
}
//if there is any query string
if (Request.QueryString.HasKeys())
{
//pass the data to a couple of variables,
var parts = Request.QueryString.Get(0);
var use = Request.QueryString.Get(1);
//put them in a new query and return the results
ViewBag.getstock = from p in Bikeshopdb.Stocks
where p.PartName == parts && (p.Road == use || p.Mtn == use || p.Hybrid == use) select new
{
p.Item, p.Price, p.Quantity
};
}
return View(Bikeshopdb.Stocks.ToList());
Use a ViewModel class to hold the query results and pass back to the view. For example:
HomeController
public class MatchingStock()
{
public int ID { get; set; }
public string Item { get; set; }
public int Price { get; set; }
public int Quantity { get; set; }
}
public ActionResult Index()
{
//...
var list =
(from p in Bikeshopdb.Stocks
where p.PartName == parts &&
(p.Road == use || p.Mtn == use || p.Hybrid == use)
select new MatchingStock() {
ID = p.ID,
Item = p.Item,
Price = p.Price,
Quantity = p.Quantity}).ToList();
ViewBag.getstock = list;
//...
}
View
#foreach (var item in (List<MatchingStock>)ViewBag.getstock)
{
#item.Item #item.Price #item.Quantity
<br />
}

MVC C# Select Where

I am trying to add filter by ID for the following:
public ActionResult Index()
{
var model = from o in new MainDBContext().OffLinePayments
select new EditOffLinePayment
{
ID = o.ID,
Amount = o.Amount
};
return View(model);
}
What I would like to do is the following:
public ActionResult Index(long? id)
{
if (id != null)
{
var model = from o in new MainDBContext().OffLinePayments
**Where Assigned_ID == id**
select new EditOffLinePayment
{
ID = o.ID,
Amount = o.Amount
};
return View(model);
}
else
{
var model = from o in new MainDBContext().OffLinePayments
select new EditOffLinePayment
{
ID = o.ID,
Amount = o.Amount
};
return View(model);
}
}
try
var model = from o in new MainDBContext().OffLinePayments
where o.Assigned_ID == id
select new EditOffLinePayment
{
ID = o.ID,
Amount = o.Amount
};
If I understand correctly, your problem is that the compiler doesn't let you write where o.Assigned_ID == id in the query.
That's because id is a Nullable<long>, which is not implicitly convertible to a long (which OffLinePayment.Assigned_ID presumably is).
You need to write where o.Assigned_ID == id.Value instead. Take a look at what the Value property does so that you don't get any surprises.
A cleaner, shorter and much more readable syntax would look like this:
public ActionResult Index(long? id){
using (var ctx = new MainDBContext())
{
var entities = ctx.OfflinePayments.Where(e => !e.HasValue || e.Assigned_ID == id.Value);
var model = entities.Select(e => new EditOfflinePayment { ID = e.ID, Amount = e.Amount }).ToList();
return View(model);
}
}

Resources