Razor post collection - asp.net

I am having an issue for posting collection. I just start learing MVC and razor.
I am writing a small questionnaire application all what I am doing populate a list of question and let the user answer the question and post the answer.
I have two class in the model Questionaire and QuestionRepository the controller have two method one for fetch the question other one to get the post data, the problem i am struggling when I populate the form with textbox I am struggling to post back the collection.
Basically what i want to achive pull the list of question, population on the UI with a text box, send the the list of question with the answer to the controller for processing some logic.
I Would really appreciate if someone can help me.
public class Questionnaire
{
public string Title {
get;
set;
}
public IList<string> Questions {
get;
set;
}
public string Answer {
get;
set;
}
}
public Questionnaire GetQuestionnaire() {
return new Questionnaire {
Title = "Geography Questions",
Questions = new List<string>
{
"What is the capital of Cuba?",
"What is the capital of France?",
"What is the capital of Poland?",
"What is the capital of Germany?"
}
};
}
public int GetCustomerAnswer() {
return 0;
}
}
Controller
public ActionResult Index()
{
var q = new QuestionRepository().GetQuestionnaire();
return View(q);
}
[HttpPost]
public ActionResult GetAnswer(QuestionRepository q) {
return View();
}
View
#model Question.Models.Questionnaire
<h2>Question List</h2>
#using(Html.BeginForm("GetAnswer","Home"))
{
for(int i=0;i< Model.Questions.Count;i++)
{
#Html.Label("Question")
<text>#Model.Questions[i]</text>
#Html.TextBox(Q => Model.Questions[i])
<br />
}
<input type="submit" name="submit" />
}

Firstly you model is wrong and does not define any relationship between questions and associated answers (you only have the ability to add one answer to all the questions). Secondly your view binds a text box to each question, allowing the user to only edit the question and not add a answer. A simple example might look like
View models
public class QuestionVM
{
public int ID { get; set; }
public string Text { get; set; }
}
public class AnswerVM
{
public QuestionVM Question { get; set; }
public int ID { get; set; }
public string Text { get; set; }
}
public class QuestionnaireVM
{
public int ID { get; set; }
public string Title { get; set; }
public List<AnswerVM> Answers { get; set; }
}
Controller
public ActionResult Create(int ID)
{
QuestionnaireVM model = new QuestionnaireVM();
// populate the model from the database, but a hard coded example might be
model.ID = 1;
model.Title = "Questionaire 1";
model.Answers = new List<AnswerVM>()
{
new AnswerVM()
{
Question = new QuestionVM() { ID = 1, Text = "Question 1" }
},
new AnswerVM()
{
Question = new QuestionVM() { ID = 2, Text = "Question 2" }
}
};
return View(model);
}
[HttpPost]
public ActionResult Create(QuestionnaireVM model)
{
// save you data and redirect
}
View
#model QuestionnaireVM
#using(Html.BeginForm())
{
#Html.DisplayFor(m => m.Title)
for(int i = 0; i < Model.Answers.Count; i++)
{
#Html.HiddenFor(m => m.Answers[i].Question.ID)
#Html.DisplayFor(m => m.Answers[i].Question.Text)
#Html.TextBoxFor(m => m.Answers[i].Text)
}
<input type="submit" />
}
This will generate a view display each question with and associated textbox to add the answer.When you post back the model will contain the ID of the questionnaire, and a collection containing the ID of each question and its associated answer.
A couple of other examples of similar issues here and here

If you want to post back something. In the [HttpPost] action, you need to return a model. At the moment, you just return a View() with no model data to display. You should do something like this:
[HttpPost]
public ActionResult GetAnswer(QuestionRepository q) {
var model = new Answer();
model.answer = q.answer;
return View(model);
}
You also need to create the model Answer.
public class Answer
{
public string answer { get; set; }
}

Related

Viewmodel nested checkbox not binding on post

I have a subscription form that contains a matrix of options. The form can be seen in screenshot Subscription table
I am having trouble with ASP.NET MVC generating appropriate ID's and then on postback having the binder populate the model with the form selections.
The add on name is down the left side and when posted back the collection of SubscriptionInputModel.Addons get populated ok. But SubscriptionInputModel.Addons[i].SubscriptionLevelCombos is null as seen in debug screenshot
The current code is using CheckBoxFor but I've also tried manually generating ID's in format:
#Html.CheckBox("addon[" + a + "].SubscriptionLevelCombo[" + i + "].AddonSelected", addon.SubscriptionLevelCombos[i].AddonSelected)
Neither format has worked and also experimented while debugging but no luck. I would appreciate any ideas. Worst case I assume I would need to read the raw form collection?
I assume the level of nested object shouldn't matter as it is all object path notation and array indexes in html tag names?
Here are snippets of current code to help illustrate what exists.
View Models
public class SubscriptionInputModel
{
//other stuff to come
//....
//add on's, listed down left of table
public List<SubscriptionInputAddonModel> Addons;
}
public class SubscriptionInputAddonModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Note { get; set; }
public List<SubscriptionInputAddonComboModel> SubscriptionLevelCombos { get; set; }
}
public class SubscriptionInputAddonComboModel
{
public int? Id { get; set; }
public decimal? AddonCost { get; set; }
public CostTimeUnitOption? CostTimeUnit { get; set; }
public bool? IsComplimentaryBySubscriptionLevel { get; set; }
public string ComboText { get; set; }
public bool AddonSelected { get; set; }
public int? AddonId { get; set; }
}
SubscriptionController
[Route("identity/subscription")]
// GET: Subscription
public ActionResult Index()
{
SubscriptionInputModel model = new SubscriptionInputModel();
ArrbOneDbContext db = new ArrbOneDbContext();
List<SubscriptionInputAddonModel> addons = Mapper.Map<Addon[], List<SubscriptionInputAddonModel>>(db.Addons.OrderBy(a => a.OrderPosition).ToArray());
model.Addons = addons;
foreach(var addon in model.Addons)
{
var addonCombos = db.Database.SqlQuery<SubscriptionInputAddonComboModel>(#"SELECT SLA.Id, AddonCost, CostTimeUnit, IsComplimentaryBySubscriptionLevel, ComboText, AddonId
FROM SubscriptionLevel L
LEFT OUTER JOIN SubscriptionLevelAddon SLA ON L.Id = SLA.SubscriptionLevelId AND SLA.AddonId = #p0
ORDER BY L.OrderPosition", addon.Id);
addon.SubscriptionLevelCombos = addonCombos.ToList();
}
return View(model);
}
[Route("identity/subscription")]
[ValidateAntiForgeryToken]
[HttpPost]
// POST: Subscription
public ActionResult Index(SubscriptionInputModel model)
{
ArrbOneDbContext db = new ArrbOneDbContext();
List<SubscriptionInputAddonModel> addons = Mapper.Map<Addon[], List<SubscriptionInputAddonModel>>(db.Addons.OrderBy(a => a.OrderPosition).ToArray());
model.Addons = addons;
//debug breakpoint to inspect returned model values
return View();
}
Index.cshtml
#model Identity_Server._Code.ViewModel.Subscription.SubscriptionInputModel
#{
ViewBag.Title = "Subscription";
}
#using (Html.BeginForm("Index", "Subscription", new { signin = Request.QueryString["signin"] }, FormMethod.Post))
{
#Html.ValidationSummary("Please correct the following errors")
#Html.AntiForgeryToken()
...
// ADD ONs ----------------------------------------------------------------------------------
#for (int a = 0; a < Model.Addons.Count; a++)
{
var addon = Model.Addons[a];
<tr>
<td class="text-left">#addon.Name
<div class="SubscriptionItemNote">#addon.Note
#Html.HiddenFor(m => m.Addons[a].Id)
</div>
</td>
#for (int i = 0; i < addon.SubscriptionLevelCombos.Count; i++)
{
<td>
#if (addon.SubscriptionLevelCombos[i].Id.HasValue)
{
if (addon.SubscriptionLevelCombos[i].AddonCost.HasValue && addon.SubscriptionLevelCombos[i].AddonCost.Value > 0)
{
#Html.Raw("<div>+ " + #addon.SubscriptionLevelCombos[i].AddonCost.Value.ToString("0.##") + " / " + #addon.SubscriptionLevelCombos[i].CostTimeUnit.Value.ToString() + "</div>")
}
else if (addon.SubscriptionLevelCombos[i].IsComplimentaryBySubscriptionLevel.HasValue && #addon.SubscriptionLevelCombos[i].IsComplimentaryBySubscriptionLevel.Value)
{
<span class="glyphicon glyphicon-ok"></span>
}
if (!string.IsNullOrEmpty(addon.SubscriptionLevelCombos[i].ComboText))
{
<div>#addon.SubscriptionLevelCombos[i].ComboText</div>
}
if (addon.SubscriptionLevelCombos[i].AddonCost.HasValue && addon.SubscriptionLevelCombos[i].AddonCost.Value > 0)
{
#Html.HiddenFor(m => m.Addons[a].SubscriptionLevelCombos[i].Id)
#Html.CheckBoxFor(m => m.Addons[a].SubscriptionLevelCombos[i].AddonSelected)
}
}
</td>
}
</tr>
}

#Html.DisplayNameFor not showing data MVC5

I have searched around and not had much luck finding a solution to my exact problem.
Model
public class PageDetailsViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Image { get; set; }
}
Controller
public ActionResult Search(int SysID)
{
var query = from r in _db.Auctions
from d in _db.Product_Details
where SysID == d.Id && r.BidStatus == "Open" && d.Id == r.Product_DetailsId
select new PageDetailsViewModel
{
Name = d.Name,
Description = d.Description,
Image = d.Image
};
return View(query);
}
View
#model IEnumerable<ProjectT.Models.PageDetailsViewModel>
#Html.DisplayNameFor(x => x.Name)
This fails to bring the name through. However, if I use a foreach
#foreach (var item in Model)
{
#item.Name
}
It brings through the name no problem.
Any help is much appreciated.
This extension method shows the value of the DisplayNameAttribute from DataAnnotations namespace. Consider this a label. Typically it is used like this:
[DisplayName("The Name")]
public string Name { get; set; }
And in the view:
#Html.DisplayNameFor(x => x.Name) <-- displays The Name
The code above will work only if the model is a single item. For the list case, as you have, you need to do some tricks, say a for loop, so you could do something like:
#Html.DisplayNameFor(x => x[i].Name): #Model[i].Name <-- displays The Name: Bill

get IEnumerable<T> in mvc post method argument

I have one model called ProductSupplier
I am passing #model IEnumerable to my View
and showing it from view
Now when i submit the form i m not getting list of IEnumerable in my http post method. I want to know the selected supplier from user.
Below is my model
public sealed class ProductSupplier
{
public int CountryId { get; set; }
public int UserId { get; set; }
public bool IsProductSupplier { get; set; }
public string CountryName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
This is my HttpGet method
public ActionResult ManageSupplier(int id)
{
var supplier = App.UsersRepo.GetSupplierForProduct(id);
return View(supplier);
}
And I am binding it via following way (U can suggest me best way I am new bee to MVC)
#model IEnumerable<ProductSupplier>
#using (Html.BeginForm("ManageSupplier", "Products", FormMethod.Post, new { role = "form") })
{ #Html.AntiForgeryToken()
foreach (var item in Model)
{
<div class="checkbox">
<label>
#Html.CheckBoxFor(x => item.IsProductSupplier, new { id = item.Email }) #item.FirstName #item.LastName (#item.Email)
</label>
</div>
}
}
And finally my HttpPost method
[HttpPost]
public ActionResult ManageSupplier(IEnumerable<ProductSupplier> obj)
{ // I m getting obj null in my argument
//I want to Get selected id from obj and want to pass in selectedSupplier
var returnVal = App.ProductRepo.AssigneSupplierForProduct(productId, selectedSupplier);
return Json(new { success = true }, JsonRequestBehavior.DenyGet);
}
can anyone suggest me where i m making mistake.
I am new to MVC any kind of suggestion highly appreciated.
Thank you in advance.
Firstable u cant do it like this.One way to do that is something like this.Here is the basic step how u do that.
1-assign for all checkbox ,checkbox change event with the unique id.
(take a look at here)
2-Cretae a jquery object and store the data when ever the checkbox clicked ,via versa
var ListProductSuppliers ={ {ProductSupplier_info_here },{ProductSupplier_info_here } };
3-later via ajax request,serilize this object(ListProductSuppliers ) and send to your method
4-on server side deserilize this to the IEnumerable<ProductSupplier>
5 later do it whatever u want with those selected suppliars

MVC 4 - Use a different model in partial view

Please bear with my noobness, I'm super new to the MVC pattern.
What I'm trying to do
I am building a profile information page for registered users on my site. This page would list data about the user, such as date of birth, telephone number, subscription status, etc.. You get the idea. I would also like to have a form to let users change their password, email address, personal information on the same page.
My problem
The user's data comes from my controller via a passed model variable:
public ActionResult Profil()
{
var model = db.Users.First(e => e.UserName == WebSecurity.CurrentUserName);
return View(model);
}
The output looks like this in my view:
<label>Phone number: </label>
#if (Model.PhoneNumber != null)
{
#Model.PhoneNumber
}
else
{
<span class="red">You haven't set up your phone number yet. </span>
}
The form in which the user could change his info would use another model, ProfileModel. So basiccaly I need to use two models in my view, one for outputting information and one for posting data. I thought that using a partial view I can achieve this, but I get this error:
The model item passed into the dictionary is of type
'Applicense.Models.User', but this dictionary requires a model item of
type 'Applicense.Models.ProfileModel'.
Here's what my call to the partial view looks like:
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary()
#Html.Partial("_ModifyProfileInfo")
}
Here's the partial view:
#model Applicense.Models.ProfileModel
<ul>
<li>
#Html.LabelFor(m => m.Email)
#Html.EditorFor(m => m.Email)
</li>
<li>
#Html.LabelFor(m => m.ConfirmEmail)
#Html.EditorFor(m => m.ConfirmEmail)
</li>
<input type="submit" value="Update e-mail" />
</ul>
And finally here's my ProfileModel:
public class ProfileModel
{
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "New e-mail address")]
public string Email { get; set; }
[DataType(DataType.EmailAddress)]
[Display(Name = "Confirm new e-mail address")]
[Compare("Email", ErrorMessage = "The e-mail and it's confirmation field do not match.")]
public string ConfirmEmail { get; set; }
}
Am I missing something? What's the proper way to do this?
Edit:
I remade my code reflecting Nikola Mitev's answer, but now I have another problem. Here's the error I get:
Object reference not set to an instance of an object. (#Model.UserObject.LastName)
This only occurs when I'm posting the changed e-mail address values. Here's my ViewModel (ProfileModel.cs):
public class ProfileModel
{
public User UserObject { get; set; }
[Required]
[DataType(DataType.EmailAddress)]
[Display(Name = "Új e-mail cím")]
public string Email { get; set; }
[DataType(DataType.EmailAddress)]
[Display(Name = "Új e-mail cím megerősítése")]
[Compare("Email", ErrorMessage = "A két e-mail cím nem egyezik.")]
public string ConfirmEmail { get; set; }
[DataType(DataType.EmailAddress)]
[Display(Name= "E-mail cím")]
public string ReferEmail { get; set; }
}
Controller:
public ActionResult Profil()
{
var User = db.Users.First(e => e.UserName == WebSecurity.CurrentUserName);
var ProfileViewModel = new ProfileModel
{
UserObject = User
};
return View(ProfileViewModel);
}
And finally here's my user.cs model class:
[Table("UserProfile")]
public class User
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
[Column("UserName")]
public string UserName { get; set; }
[Column("Email")]
[Required]
public string Email { get; set; }
[Column("FirstName")]
public string FirstName { get; set; }
[Column("LastName")]
public string LastName { get; set; }
[Column("PhoneNumber")]
public string PhoneNumber { get; set; }
... You get the idea of the rest...
I'm thinking it's happening because the model is trying to put data in each required columns into the database.
Edit2:
The httppost method of my Profil action:
[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public ActionResult Profil(ProfileModel model)
{
if (ModelState.IsValid)
{
//insert into database
return Content("everything's good");
}
else
{
//outputs form errors
return View(model);
}
}
The best way to handle this situation is to use and pass viewModel to your Profile controller, viewModel is wrapper class for multiple objects that you want to pass to your view.
public class ProfileUserViewModel
{
public ProfileModel ProfileModelObject {get; set;}
public UserModel UserModelObject {get; set;}
}
Your controller should look like:
public ActionResult Profil()
{
var profileModel = db.Users.First(e => e.UserName == WebSecurity.CurrentUserName);
var userModel = //fetch from db.
var pmViewModel = new ProfileUserViewModel
{
ProfileModelObject = profileModel,
UserModelObject = userModel
};
return View(pmViewModel);
}
And finally your view :
#model Applicense.Models.ProfileUserViewModel
<label>Phone number: </label>
#if (Model.ProfileModelObject.PhoneNumber != null)
{
#Model.PhoneNumber
}
else
{
<span class="red">You haven't set up your phone number yet. </span>
}
There is an overload of #Html.Partial which allows you to send ViewData as defined in your controller - this is the method I generally use for partial views.
In your controller define ViewData["mypartialdata"] as ViewDataDictionary. Then in your view
#Html.Partial("_ModifyProfileInfo",ViewData["mypartialdata"])
In your [HttpPost] profil function, if modelstate.isvalid is false, you return your edit view, but you need to define your pmViewModel again , other wise your partial view will not have an object to display. Try using the following and let us know what happens
[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public ActionResult Profil(ProfileModel model)
{
if (ModelState.IsValid)
{
//insert into database
return Content("everything's good");
}
else
{
//outputs form errors
var pmViewModel = new ProfileUserViewModel
{
ProfileModelObject = profileModel,
UserModelObject = userModel
};
return View(model);
}
}
While I know this question has been asked longtime ago however some people might still face a similar problem. One easy solution I use to pass or have more than one view model on a page is to use a ViewBag to hold the second object and refer to it in the view. See example bellow.
In your controller do this:
Obj2 personalDets = new Obj2();
DbContext ctx = new DbContext();
var details = ctx.GetPersonalInformation;
foreach(var item in details) {
personalDets.Password = item.Password;
personalDets .EmailAddress = item.EmailAddress;
}
ViewBag.PersonalInformation = personalDets;
Then in your view those properties become readily available for you

How to make simple calculations using model items and an input from a form in ASP.net MVC 3?

Am new to programming and ASP.net MVC 3 so don't be surprised by my lack of knowledge on this.. Okay, I want to multiply two decimals, One decimal comes from the form that a user fills and the other decimal comes from the Model class (gets it from the database).
I have two Model classes called RATE & PROJECTMATERIAL . The RATE class has an item called Amount that states the amount of a Rate and the PROJECTMATERIAL class has an item quantity. The classes are related and i want to be able to say variable1 = quantity*Rates.amount and return variable1 to the my Index, Delete, Details views. I don't want to store variable1 to my database but i just want to display in my views.....but i don't know how and where to do it
Code from Project material class..
public class ProjectMaterial
{
public int ProjectMaterialID { get; set; }
[Required]
[Display(Name = "Scope Name")]
public int? ScopeID { get; set; }
[Required]
[Display(Name = "Rate Code")]
public int? RateID { get; set; }
[Required]
[Display(Name = "Quantity")]
public decimal Quantity { get; set; }
public virtual Scope Scopes { get; set; }
public virtual Rate Rates { get; set; }
}
Code from scope class..
public class Rate
{
public int RateID { get; set; }
[Required]
[Display(Name = "Rate Code")]
public int RateCode { get; set; }
[Required]
[Display(Name = "Unit")]
public string Unit { get; set; }
[Required]
[Display(Name = "Description")]
public string Description { get; set; }
[Required]
[Display(Name = "Amount")]
public decimal Amount { get; set; }
public virtual ICollection<ProjectMaterial> ProjectMaterials { get; set; }
}
Code from project controller class...
public class ProjectMaterialController : Controller
{
private ContructorContext db = new ContructorContext();
//
// GET: /ProjectMaterial/
public ViewResult Index()
{
var projectmaterials = db.ProjectMaterials.Include(p => p.Scopes).Include(p => p.Rates);
return View(projectmaterials.ToList());
}
//
// GET: /ProjectMaterial/Details/5
public ViewResult Details(int id)
{
ProjectMaterial projectmaterial = db.ProjectMaterials.Find(id);
return View(projectmaterial);
}
//
// GET: /ProjectMaterial/Create
public ActionResult Create()
{
ViewBag.ScopeID = new SelectList(db.Scopes, "ScopeID", "ScopeName");
ViewBag.RateID = new SelectList(db.Rates, "RateID", "Unit");
return View();
}
//
// POST: /ProjectMaterial/Create
[HttpPost]
public ActionResult Create(ProjectMaterial projectmaterial)
{
if (ModelState.IsValid)
{
db.ProjectMaterials.Add(projectmaterial);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.ScopeID = new SelectList(db.Scopes, "ScopeID", "ScopeName", projectmaterial.ScopeID);
ViewBag.RateID = new SelectList(db.Rates, "RateID", "Unit", projectmaterial.RateID);
return View(projectmaterial);
}
//
// GET: /ProjectMaterial/Edit/5
public ActionResult Edit(int id)
{
ProjectMaterial projectmaterial = db.ProjectMaterials.Find(id);
ViewBag.ScopeID = new SelectList(db.Scopes, "ScopeID", "ScopeName", projectmaterial.ScopeID);
ViewBag.RateID = new SelectList(db.Rates, "RateID", "Unit", projectmaterial.RateID);
return View(projectmaterial);
}
//
// POST: /ProjectMaterial/Edit/5
[HttpPost]
public ActionResult Edit(ProjectMaterial projectmaterial)
{
if (ModelState.IsValid)
{
db.Entry(projectmaterial).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.ScopeID = new SelectList(db.Scopes, "ScopeID", "ScopeName", projectmaterial.ScopeID);
ViewBag.RateID = new SelectList(db.Rates, "RateID", "Unit", projectmaterial.RateID);
return View(projectmaterial);
}
//
// GET: /ProjectMaterial/Delete/5
public ActionResult Delete(int id)
{
ProjectMaterial projectmaterial = db.ProjectMaterials.Find(id);
return View(projectmaterial);
}
//
// POST: /ProjectMaterial/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
ProjectMaterial projectmaterial = db.ProjectMaterials.Find(id);
db.ProjectMaterials.Remove(projectmaterial);
db.SaveChanges();
return RedirectToAction("Index");
}
Thanx in advance guys!! really need your help.
Seeing as you say you're new to MVC, I've given you a few options and explained which is best and why, because it's better to understand now so you don't get in to bad habits, especially if you start building larger projects.
You don't necessarily need to create a variable, because you can do that calculation in your view. Because you are passing the domain model directly to the view you can do (in razor):
#(Model.Quantity * Model.Rates.Amount)
Although this is the easiest option I wouldn't necessarily recommend this as views should be dumb - see ASP.NET MVC: How dumb should my view be?.
Another option is to do the calculation in the controller and pass the value in the ViewBag, e.g.:
public ViewResult Details(int id)
{
ProjectMaterial projectmaterial = db.ProjectMaterials.Find(id);
ViewBag.Price = projectmaterial.Quantity * projectmaterial.Rates.Amountl
return View(projectmaterial);
}
Then you could use it in your view like:
#ViewBag.Price
Again, this is easy but I wouldn't recommend it, as ViewBag isn't strongly typed - see Is using ViewBag in MVC bad?.
You could put a property on your ProjectMaterial class like, which is a neat solution.
public decimal Price
{
get
{
return Quantity * Rates.Amount;
}
}
However, if Price is a property that is only ever used within your views (ie you just display it) then it probably shouldn't be in your domain model, as your domain model is just that - storing and accessing the raw data.
Maybe the best way is to create a viewmodel specific to your view (see http://stephenwalther.com/blog/archive/2009/04/13/asp.net-mvc-tip-50-ndash-create-view-models.aspx) with a Price propert. This means that the property is only used where it is needed, the domain model remains just that, your view remains dumb and your domain model is not exposed to your view. See Why Two Classes, View Model and Domain Model? also for a good explanation of view models
You could add a property to your ProjectMaterial model:
public decimal Price
{
get
{
return Quantity * Rates.Amount;
}
}
You might want to have a model function with instances of your self.rate, and self.material items passed on from your views. Or otherwise you can individually calculate the values of the multiplication in each view.
Either way, you should be able to store the copy over the value of multiplication (variable1) in the view's bag, and pass it onto each view without having to save it in the DB.
ViewBag.variable1 = rate*material
return View()
#(int.Parse(variable) * your value)
Additional to all the answers you can use Data Format String in model class, and Html Helper in View to maintain formatting in displayed results for numeric types, by modifying returned attribute in the Controller.
The purpose of applying the formatting in the model class, and the value transformation in the controller and keeping the view standard, is to achieve separation of concerns (SoC) for easier maintenance, and control over the code.
Consider this example:
Products Class Property
[Display(Name = "Max Disc %")]
[DisplayFormat(DataFormatString = "{0:P1}", ApplyFormatInEditMode = true)]
public decimal MaxDiscountRate { get; set; }
Products Controller
[HttpGet]
public ActionResult Details(int id)
{
if (id == 0)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Products products = _uow.Products.GetById(id);
if (products == null)
{
return HttpNotFound();
}
else
{
products.MaxDiscountRate /= 100;
}
return View(products);
}
Products Details View
<div class="detail">
<h5 class="text-teal">#Html.DisplayNameFor(model => model.MaxDiscountRate)</h5>
<span class="text-peru">#Html.DisplayFor(model => model.MaxDiscountRate)</span>
</div>

Resources