Addition of two numbers in MVC - asp.net

I am trying to add two numbers in MVC.
My requirement is "I have 2 text boxes in View from which I have to retrieve data to controller"
View :
#using (Html.BeginForm("Addition", "Addition", FormMethod.Post))
{
<input id="Text1" type="text" value=#ViewBag.a name="firstNum" />
<input id="Text2" type="text" value=#ViewBag.b name="secondNum" />
<input id="Text3" type="text" value=#ViewBag.result />
<input type="submit" value="Submit" />
}
Controller Name : Addition
Action Name: Addition
[HttpPost]
public ActionResult Addition(FormCollection fc)
{
string[] keyss = fc.AllKeys;
ViewBag.a = fc.Keys[0];
ViewBag.b = fc.Keys[1];
ViewBag.total = ViewBag.a + ViewBag.b;
return View();
}
Now, from this form collection I want to retrieve values of textboxes.
Thanks.

One of the powers of MVC is the model binder - which you are completely ignoring here. Create a view model to match the expected content of your view
public class AdditionViewModel
{
public int A { get; set; }
public int B { get; set; }
public int Result { get; set; }
}
Use this as the expected parameter in your action
[HttpPost]
public ActionResult Addition(AdditionViewModel model)
{
model.Result = model.A + model.B;
return View(model);
}
Then finally in your view
#model AdditionViewModel
#using (Html.BeginForm("Addition", "Addition", FormMethod.Post))
{
#Html.EditorFor(x => x.A)
#Html.EditorFor(x => x.B)
#Html.DisplayFor(x => x.Result)
<input type="submit" value="Submit" />
}

Assuming you get the data in to ur controller , afterwards you just add Addition view and use
#ViewBag.total simple or you also can use viewdata or tempdata in case if u required .

The better way is
[HttpPost]
public ActionResult Addition(int firstNum, int secondNum )
{
ViewBag.Result=firstNum+secondNum;
return View();
}
Make sure you are doing a Numeric validation at client side

Related

Populating data from last row in form when creating a new entry

I have a form to create new data entries for comments. Creating completely new entries works fine. However, when I have already created one entry for my entity I want to populate the data from the last entry in my form.
I have tried to modify the OnGet action to include the data from the last entry. I copied the OnGet code from the Edit view into the Create view. However, if I do this, the Create page is not displayed anymore.
I have the following model:
public class ProjectComment
{
public int Id { get; set; }
public int? ProjectId { get; set; }
public Project Project { get; set; }
public int RAGStatusId { get; set; }
public RAGStatus RAGStatus { get; set; }
public string StatusComment { get; set; }
public string EscalationComment { get; set; }
public string GeneralComment { get; set; }
public double? EOQ { get; set; }
public DateTime LastUpdateDate { get; set; }
public ProjectComment ()
{
this.LastUpdateDate = DateTime.UtcNow;
}
The create form Create.cshtml:
#page
#model SimpleProjectReporting.Pages.ClientDetails.CreateModel
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>ProjectComment</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="ProjectComment.ProjectId" class="control-label"></label>
<select asp-for="ProjectComment.ProjectId" class="form-control" asp-items="ViewBag.ProjectId"><option value="" default="" selected="">-- Select --</option></select>
</div>
<div class="form-group">
<label asp-for="ProjectComment.RAGStatusId" class="control-label"></label>
<select asp-for="ProjectComment.RAGStatusId" class="form-control" asp-items="ViewBag.RAGStatusId"><option value="" default="" selected="">-- Select --</option></select>
</div>
<div class="form-group">
<label asp-for="ProjectComment.StatusComment" class="control-label"></label>
<input asp-for="ProjectComment.StatusComment" class="form-control" />
<span asp-validation-for="ProjectComment.StatusComment" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ProjectComment.EOQ" class="control-label"></label>
<input asp-for="ProjectComment.EOQ" class="form-control" />
<span asp-validation-for="ProjectComment.EOQ" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
The original Create.cshtml.cs action:
[BindProperty]
public ProjectComment ProjectComment { get; set; }
public IActionResult OnGet()
{
ViewData["ProjectId"] = new SelectList(_context.Project.Where(a => a.IsArchived == false), "Id", "ProjectName");
ViewData["RAGStatusId"] = new SelectList(_context.RAGStatus.Where(a => a.IsActive == true), "Id", "RAGStatusName");
return Page();
}
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://aka.ms/RazorPagesCRUD.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.ProjectComment.Add(ProjectComment);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
The modified Create.cshtml.cs OnGet action:
public async Task<IActionResult> OnGetAsync(int? id)
{
if (id == null)
{
return NotFound();
}
ProjectComment = await _context.ProjectComment
.Include(p => p.Project)
.Include(p => p.RAGStatus).FirstOrDefaultAsync(m => m.Id == id);
if (ProjectComment == null)
{
return NotFound();
}
When modifying the action the way I did it, the page is not displayed anymore (404 error).
I would like to populate the create form with the data from the last entry in the database. If there is no comment, the create page would only populate the name of the project.
You are not sending the "id" parameter to your post action I guess.
So could you please try to adding this line under your form tag:
<form method="post">
<input type="hidden" id="ProjectComment.Id" name="id" value="ProjectComment.Id" />
You are trying to reach the last record of your ProjectComment table.
There are more than one methods to find the last record of your data table. But lets keep it simple.
You have an integer based identity column, which is Auto Increment. So you can simply use below methods to reach out the last created data of your table.
In your OnGetAsync() method:
//maxId will be the maximum value of "Id" columns. Which means that the maximum value is the last recorded value.
int maxId = _context.ProjectComment.Max(i => i.Id);
//And this line will bring you the last recorded "ProjectComment" object.
var projectComment = _context.ProjectComment.Find(maxId);
//You can assign it to your above 'ProjectComment' property if you want to..
ProjectComment = projectComment
Now, since you've find the last recorded data in your database, you can use that object.
Firstly, thanks to Burak for providing the above solution, which works when you want to display the last row in the table. This helped me solving my issue by using the same approach and finding the record based on the Id of the record.
I have amended the code from the Create.cshtml.cs file as follows:
public async Task<IActionResult> OnGetAsync(int? id, int projectid)
{
//This will find the "ProjectComment" object.
var projectComment = _context.ProjectComment.Find(id);
//This will display the 'ProjectComment' on the page
ProjectComment = projectComment;
if (id == null)
{
ProjectComment = projectComment;
ViewData["ProjectId"] = new SelectList(_context.Project, "Id", "ProjectName", projectid);
return Page();
}
ViewData["ProjectId"] = new SelectList(_context.Project, "Id", "ProjectName");
return Page();
}
I am using the int projectid to populate the drop down menu of the project when there is no comment create yet.

Use multiple forms in one view and submit them to several different tables

I have view that in this view, I want to pass some models to it. I'm passing models like this:
#Html.Partial("_Project", Model.AllProjects)
#Html.Partial("_Blog", Model.AllBlog)
#Html.Partial("_Comment", Model.AllComments)
this view feeds on a viewModel (HomeMultiViewModel) that contains some models like this:
public class HomeMultiViewModel
{
public List<Project> AllProjects { get; set; }
public List<Blog> AllBlog { get; set; }
public List<Blog> SearchInBlog { get; set; }
public List<Costumer> AllCostumers { get; set; }
public List<Comments> AllComments { get; set; }
}
Except these, I have 2 forms in this view that the values of one them should be sent to a model named ContactYou, and the values of another one should be send to a model names advise.
This is first form in my view:
<form class="UswithYouForm">
<input type="tel" class="UswithYouFormInput" placeholder="Phone number.." />
<button type="submit" class="UswithYouFormButtom">Submit</button>
</form>
This is the second for in that view:
<form class="adviseForm">
<input type="text" class="form-control" placeholder="Your Name" />
<input type="tel" class="form-control" placeholder="Phone number" />
<input type="text" class="form-control" placeholder="Subject" />
<textarea class="form-control" placeholder="Message..."></textarea>
<button class="slide__text-link">Send your request!</button>
</form>
And at last this is my controller for that view:
namespace Atawin.Controllers
{
public class HomeController : Controller
{
private readonly ApplicationDbContext _context;
private readonly IServiceProvider _serviceProvider;
public HomeController(ApplicationDbContext context, IServiceProvider serviceProvider)
{
_context = context;
_serviceProvider = serviceProvider;
}
public IActionResult Index()
{
HomeMultiViewModel model = new HomeMultiViewModel();
model.AllProjects = (from p in _context.projects select p).ToList();
model.AllBlog = (from b in _context.blogs select b).ToList();
model.AllCostumers = (from c in _context.costumers select c).ToList();
model.AllComments = (from com in _context.comments select com).ToList();
ViewBag.RootPath = "/upload/Norm/";
return View(model);
}
public IActionResult Search(string searchedTxt)
{
HomeMultiViewModel model = new HomeMultiViewModel();
model.AllBlog = (from b in _context.blogs select b).ToList();
model.AllCostumers = (from c in _context.costumers select c).ToList();
model.SearchInBlog = (from sb in _context.blogs where sb.Title.Contains(searchedTxt) orderby sb.Id descending select sb).Take(15).ToList();
ViewBag.RootPath = "/upload/Norm/";
ViewBag.SearchedWords = searchedTxt;
return View(model);
}
// i want an action here to solve my problem
}
}
I actually reed the questions like this on the whole websites, but I can't solve my problem. If you need more to answer this question tell me so I'll send theme to you.

How to prevent controller from sending identity column to database

Controller Action:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult New_Shelf(Shelf shelf)
{
shelf.User_Id = int.Parse(Request.Cookies["UserId"].Value);
db_shelf.Shelves.Add(shelf);
db_shelf.SaveChanges();
return RedirectToAction("Index", "Home");
}
Model:
namespace Book_shelf.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
public partial class Shelf
{
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Name { get; set; }
public int Size { get; set; }
[ForeignKey("Id")]
public int User_Id { get; set; }
}
}
View:
#model Book_shelf.Models.Shelf
#using (Html.BeginForm("New_Shelf", "Home", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<label style="font-family:sans-serif">Name</label>
<br />
#Html.TextBoxFor(a => a.Name)
<br />
<br />
<label style="font-family:sans-serif">Size</label>
<br />
#Html.TextBoxFor(a => a.Size)
<br />
<br />
<button class="btn btn-sm" type="submit"> Add</button>
}
Error:
Cannot insert explicit value for identity column in table 'Shelf' when >IDENTITY_INSERT is set to OFF.
I am new to ASP.net MVC and Entity Framework.
I am trying to Insert a new row for my table 'Shelf'.But it looks like that the view is sending Id as well when posting data to Action.I Tried to Log the value of shelf.Id in the action and it was '0'.How do i prevent the view to send any data in for Id property?
The problem was in shelf.edmx file,I checked the properties of Id column in the table designer and set the storedGeneratedPattern value to identity which was previously set to none.

Partial views inside my asp.net mvc will ignore all the model data annotations

I have the following action method which render the following partial view:-
public ActionResult CreateVMNetwork(int vmid)
{
AssignIps vmips = new AssignIps()
{
TechnologyIP = new TechnologyIP() { TechnologyID = vmid},
IsTMSIPUnique = true,
IsTMSMACUnique = true
};
return PartialView("_CreateNetworkInfo",vmips);
}
The partial view is :-
model TMS.ViewModels.AssignIps
#if (this.ViewContext.FormContext == null)
{
this.ViewContext.FormContext = new FormContext();
}
#using (Ajax.BeginForm("CreateVMNetwork", "VirtualMachine", new AjaxOptions
{
InsertionMode = InsertionMode.InsertAfter,
UpdateTargetId = "networktable",
LoadingElementId = "loadingimag",
HttpMethod= "POST",
OnSuccess="submitform"
}))
{
#Html.ValidationSummary(true)
#Html.HiddenFor(model=>model.TechnologyIP.TechnologyID)
#Html.AntiForgeryToken()
<div>
<span class="f">IP Address</span>
#Html.EditorFor(model => model.TechnologyIP.IPAddress)
#Html.ValidationMessageFor(model => model.TechnologyIP.IPAddress)
<input type="CheckBox" name="IsTMSIPUnique" value="true" #(Html.Raw(Model.IsTMSMACUnique ? "checked=\"checked\"" : "")) /> IP Unique. |
<span class="f"> MAC Address</span>
#Html.EditorFor(model => model.TechnologyIP.MACAddress)
#Html.ValidationMessageFor(model => model.TechnologyIP.MACAddress)
<input type="CheckBox" name="IsTMSMACUnique" value="true" #(Html.Raw(Model.IsTMSMACUnique ? "checked=\"checked\"" : "")) /> MAC Unique.
</div>
<input type="submit" value="Save" class="btn btn-primary"/>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
but all the data annotation on the view model will not fire on the partial view , the AssignIps view model class is :-
namespace TMS.ViewModels
{
public class AssignIps
{
public TechnologyIP TechnologyIP { get; set; }
public bool IsTMSIPUnique { get; set; }
public bool IsTMSMACUnique { get; set; }
}
}
and he TechnologyIP model class is :-
namespace TMS.Models
{
[MetadataType(typeof(TechnologyIP_Validation))]
public partial class TechnologyIP
{}}
namespace TMS.Models
{
public class TechnologyIP_Validation
{
[Required]
public string IPAddress { get; set; }
but the [Required] data annotation on the TechnologyIP model, will not fire on the partial view,, can anyone adovce please?
Thanks.
Sections defined in your layout view don't get populated when using PartialViewResult, so the unobtrusive validation scripts are not being added.
You can test this by creating an action on your controller that just returns a partial view, and then call this via $.get() (using jQuery, obviously). If you use console.log(), you can inspect the result in Firebug. You could also use something like Fiddler; regardless, if you look at the HTML returned you will not see the script references anywhere.
Exactly, a wrong practice is to have:
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
in the partial view, try to do it just putting
#Scripts.Render("~/bundles/jqueryval")
and it should work!

How to pass information between different web page

Hi everyone I am trying to pass information between diferent page, but I don't know how.
I have this form with Html.ActionLink inside
<% using (Html.BeginForm("Save", "Envi"))
{%>
<%: Html.ValidationSummary(true)%>
<div class="editor-label">
<%: Html.Label("Description:")%>
</div>
<div class="editor-field">
<%: Html.TextBox("info", lp.Description)%>
...
<div>
<%: Html.ActionLink("Change Image", "ChangeImg", "Envi", new {id=lp}, new {id="cambio"})%>
...
<p>
<input type="submit" value="Save" name="<%= lp.Id %>"/>
</p>
<% } %>
<% } %>
When I click the Html.ActionLink I show other page (dialog with fancyBox) where I select an Image.
I want to pass all data from the Form to this page. Now when I show the form again I have the new data, no the old data.
How can I do that???
Thanks.
You are suggested to use TempData dictionary. This will be available for only the next request.
Quoting from MSDN:
An action method can store data in the controller's TempDataDictionary
object before it calls the controller's RedirectToAction method to
invoke the next action. The TempData property value is stored in
session state. Any action method that is called after the
TempDataDictionary value is set can get values from the object and
then process or display them. The value of TempData persists until it
is read or until the session times out. Persisting TempData in this
way enables scenarios such as redirection, because the values in
TempData are available beyond a single request.
Hope this gives your answer.
Ideally, I believe the form should submit to a single action.
So the controller may look like this:
public class HomeController : Controller
{
public ViewResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(ItemModel itemModel, string submit)
{
//I'm not sure why I need this but the fields display with empty results on my machine otherwise
ModelState.Clear();
if (submit == "edit")
{
this.TempData.Add("item", itemModel);
return View("ChangeImage", new ImageModel { ImageName = itemModel.ImageName });
}
else
{
//perform save here
return RedirectToAction("ViewAfterSavePerformed");
}
}
[HttpPost]
public ViewResult Image(ImageModel imageModel)
{
ItemModel itemModel = (ItemModel)this.TempData["item"];
itemModel.ImageName = imageModel.ImageName;
return View("Index", itemModel);
}
}
With the following view models:
public class ItemModel
{
public string Description { get; set; }
public string ImageName { get; set; }
}
public class ImageModel
{
public string ImageName { get; set; }
}
And the following views:
Index:
<h2>Index</h2>
#using (Html.BeginForm())
{
<p>Description: #Html.EditorFor(m => m.Description)</p>
<p>Image: #Html.EditorFor(m => m.ImageName)</p>
<input type="submit" name="submit" value="edit" />
<input type="submit" name="submit" value="save" />
}
Change Image:
<h2>ChangeImage</h2>
#using (Html.BeginForm("Image", "Home"))
{
<p>Image: #Html.EditorFor(m => m.ImageName)</p>
<input type="submit" name="submit" value="save image" />
}
Hopefully this should may sense even though i've used razor syntax.

Resources