Adding extra info before writing to database - asp.net-mvc

In the Action method code below, all the data from the form is included as parameters, but what if I also would like to add to the table something more like the users Entity ID
var userID = User.Identity.GetUserId();
How can I add that to the Customers object before it's written to the table? One way could perhaps be to add it into the HTML and the form as hidden, but I guess it would be unsecure to have that visible in the code?
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,FirtsName,LastName,PhoneNumber")] Customers customers)
{
var userID = User.Identity.GetUserId();
if (ModelState.IsValid)
{
db.Customers.Add(customers);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(customers);
}

You can just set some property before save.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,FirtsName,LastName,PhoneNumber")] Customers customers)
{
if (ModelState.IsValid)
{
customers.UserID = User.Identity.GetUserId();
db.Customers.Add(customers);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(customers);
}

Related

MVC i want to insert client data ip address,and date on database now but action not done

MBG_ITEntities db = new MBG_ITEntities();
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(HitCounter obj)
{
DateTime time = DateTime.Now;
obj.IPAddress = Request.UserHostAddress;
obj.CreateDate = time;
db.HitCounter.Add(obj);
db.SaveChanges();
return View(obj);
}
i want action done on load page.
i want the action done from controller only

Passing a variable from [HttpPost] method to [HttpGet] method

I am redirecting the view from [HttpPost] method to [HttpGet] method. I have gotten it to work, but want to know if this is the best way to do this.
Here is my code:
[HttpPost]
public ActionResult SubmitStudent()
{
StudentViewModel model = TempData["model"] as StudentResponseViewModel;
TempData["id"] = model.Id;
TempData["name"] = model.Name;
return RedirectToAction("DisplayStudent");
}
[HttpGet]
public ActionResult DisplayStudent()
{
ViewData["id"] = TempData["id"];
ViewData["name"] = TempData["name"];
return View();
}
View:
<%# Page
Language="C#"
Inherits="System.Web.Mvc.ViewPage"
%>
<html>
<head runat="server">
<title>DisplayStudent</title>
</head>
<body>
<div>
<%= ViewData["id"]%> <br />
<%= ViewData["name"]%>
</div>
</body>
</html>
There are basically 3 techniques in ASP.NET MVC to implement the PRG pattern.
TempData
Using TempData is indeed one way of passing information for a single redirect. The drawback I see with this approach is that if the user hits F5 on the final redirected page he will no longer be able to fetch the data as it will be removed from TempData for subsequent requests:
[HttpPost]
public ActionResult SubmitStudent(StudentResponseViewModel model)
{
if (!ModelState.IsValid)
{
// The user did some mistakes when filling the form => redisplay it
return View(model);
}
// TODO: the model is valid => do some processing on it
TempData["model"] = model;
return RedirectToAction("DisplayStudent");
}
[HttpGet]
public ActionResult DisplayStudent()
{
var model = TempData["model"] as StudentResponseViewModel;
return View(model);
}
Query string parameters
Another approach if you don't have many data to send is to send them as query string parameters, like this:
[HttpPost]
public ActionResult SubmitStudent(StudentResponseViewModel model)
{
if (!ModelState.IsValid)
{
// The user did some mistakes when filling the form => redisplay it
return View(model);
}
// TODO: the model is valid => do some processing on it
// redirect by passing the properties of the model as query string parameters
return RedirectToAction("DisplayStudent", new
{
Id = model.Id,
Name = model.Name
});
}
[HttpGet]
public ActionResult DisplayStudent(StudentResponseViewModel model)
{
return View(model);
}
Persistence
Yet another approach and IMHO the best consists into persisting this model into some data store (like a database or something and then when you want to redirect to the GET action send only an id allowing for it to fetch the model from wherever you persisted it). Here's the pattern:
[HttpPost]
public ActionResult SubmitStudent(StudentResponseViewModel model)
{
if (!ModelState.IsValid)
{
// The user did some mistakes when filling the form => redisplay it
return View(model);
}
// TODO: the model is valid => do some processing on it
// persist the model
int id = PersistTheModel(model);
// redirect by passing the properties of the model as query string parameters
return RedirectToAction("DisplayStudent", new { Id = id });
}
[HttpGet]
public ActionResult DisplayStudent(int id)
{
StudentResponseViewModel model = FetchTheModelFromSomewhere(id);
return View(model);
}
Each method has its pros and cons. Up to you to choose which one suits best to your scenario.
If you are inserting this data into a database then you should redirect them to a controller action that has this data in the route:
/Students/View/1
You can then write code in the controller to retrieve the data back from the database for display:
public ActionResult View(int id) {
// retrieve from the database
// create your view model
return View(model);
}
One of the overrides of RedirectToAction() looks like that:
RedirectToAction(string actionName, object routeValues)
You can use this one as:
[HttpPost]
public ActionResult SubmitStudent()
{
StudentViewModel model = TempData["model"] as StudentResponseViewModel;
return RedirectToAction("DisplayStudent", new {id = model.ID, name = model.Name});
}
[HttpGet]
public ActionResult DisplayStudent(string id, string name)
{
ViewData["id"] = TempData["id"];
ViewData["name"] = TempData["name"];
return View();
}
Hope that works.
This is the classic Post-Redirect-Get pattern (PRG) and it looks fine but I would add one bit of code. In the DisplayStudent method check if your TempData variables are not null otherwise do a redirect to some default Index action. This is in case a user presses F5 to refresh the page.
public ActionResult DisplayStudent()
{
if(TempData["model"] == null)
{
return RedirectToAction("Index");
}
var model = (StudentResponseViewModel)TempData["model"];
return View(model);
}
public ViewResult Index()
{
IEnumerable<StudentResponseViewModel> students = GetAllStudents();
return View(students);
}

Is it possible to retrieve the posted form fields from within a parameterless HttpPost action method?

Non-HttpPost
public ActionResult Edit(int id)
{
var model = repository.GetModel(id);
if(model==null) return View("NotFound");
return View(model);
}
HttpPost
[HttpPost]
public ActionResult Edit()
{
// First of all, we retrieve the id from the posted form field.
// But I don't know how to do.
var model = repository.GetModel(id);
if(model==null) return View("NotFound");
if(!TryUpdateModel(model))
return View(model);
repository.SaveChanges();
RedirectToAction("Status","Controller");
}
Is it possible to retrieve the posted form fields from within a parameterless HttpPost action method?
For posted form values:
var id = Request.Form["id"];
or:
[HttpPost]
public ActionResult Edit(FormCollection fc)
{
var id = fc["id"];
...
}
or for any request value (including form posted):
var id = Request["id"];

ASP.NET MVC ModelState.IsValid doesnt work

I've this controller's method for create
[HttpPost]
public ActionResult Create(Topic topic)
{
if (ModelState.IsValid)
{
topicRepo.Add(topic);
topicRepo.Save();
return RedirectToAction("Details", new { id = topic.ID });
}
return View(topic);
}
and this for edit
[HttpPost]
public ActionResult Edit(int id, FormCollection formCollection)
{
Topic topic = topicRepo.getTopic(id);
if (ModelState.IsValid)
{
UpdateModel<Topic>(topic);
topicRepo.Save();
return RedirectToAction("Details", new { id = topic.ID });
}
return View(topic);
}
Both of these methods use common partial page (.ascx).
Validation works when I try to create topic but doesn't work when I try to edit it
That's normal. In the first example you are using a model as action parameter. When the default model binder tries to bind this model from the request it will automatically invoke validation and when you enter the action the ModelState.IsValid is already assigned.
In the second example your action takes no model, only a key/value collection and without a model validation makes no sense. Validation is triggered by the UpdateModel<TModel> method which in your example is invoked after the ModelState.IsValid call.
So you could try this:
[HttpPost]
public ActionResult Edit(int id)
{
Topic topic = topicRepo.getTopic(id);
UpdateModel<Topic>(topic);
if (ModelState.IsValid)
{
topicRepo.Save();
return RedirectToAction("Details", new { id = topic.ID });
}
return View(topic);
}

MVC View Model Get Child Object

I have a main Contact and ContactViewModel . How do I get contact model and update it to the database ?
[HttpPost]
public ActionResult EditContact(ContactFormViewModel contactView) {
}
I was doing like this before I needed ViewModel
[HttpPost]
public ActionResult EditContact(int id, FormCollection collection) {
Contact contact = repository.GetContactById(id);
if (TryUpdateModel(contact, "Contact")) {
repository.Save();
return RedirectToAction("Index");
return View(new ContactFormView Model(contact));
}
}
It's a bit easier when you have a view model (you can forget about FormCollection and TryUpdateModel):
[HttpPost]
public ActionResult EditContact(ContactViewModel contact)
{
if (ModelState.IsValid)
{
// the model is valid => we can save it to the database
Contact contact = mapper.Map<ContactViewModel, Contact>(contact);
repository.Save(contact);
return RedirectToAction("Index");
}
// redisplay the form to fix validation errors
return View(contact);
}
where mapper converts between the view model and models. AutoMapper is a great choice for this task.

Resources