How do I add new information to the database? - asp.net-mvc-4

I am working with the following code. I have set up the form, models, and controllers necessary to add an item. I know the code works because after entering text into the text field I am redirect to the correct page. My question is: How do I add the text entered by the user into the default database?
public ActionResult TruckAdd()
{
ViewBag.DisplayText = "Add A Truck";
return View();
}
[HttpPost]
public ActionResult TruckAdd(RegisterTruckModel model)
{
if (ModelState.IsValid)
{
// Attempt to register the Truck
try
{
return RedirectToAction("Index", "Dashboard");
}
catch
{
}
}
// If we got this far, something failed, redisplay form
return View(model);
}

Related

Redirecting to a response view with a model does not keep model properties

I have a form view that submits form data to the post action on a controler and then redirects to another view that uses logic to display either a success or failure, but the new view just shows blank values for model properties. Here is the post action:
[HttpPost]
public ActionResult ContactUs(TTT.Models.ContactUsModel model)
{
logger.Info(model.URL + "Contact Us Form submitted");
var userkey = model.ValidationKey;
var sessionkey = Session["ContactUsKey"];
var lastsubmission = Session["ContactUsTime"];
model.Response = "success";
//first check if honeypot was populated via a bot and if so send it to the success page without doing anything
if (model.WorkAddress != "")
{
logger.Info("honeypot triggered");
return View("ContactUsResponse", model);
}
I'll leave out the remainder of the controler, but
And here is the view it's redirecting to:
#using TTT.Models
#using Sitecore.Mvc
#model ContactUsModel
<h1>#Model.Title</h1>
<div>#Model.Body</div>
<div>
#if (#Model.Response == "fail")
{
#Model.Failure;
} else
{
#Model.Success;
}
</div>
Instead of returning a new view, call RedirectToAction and return new view from that controller.
[HttpPost]
public ActionResult ContactUs(TTT.Models.ContactUsModel model)
{
//--- Code omitted for brevity
if (model.WorkAddress != "")
{
logger.Info("honeypot triggered");
return RedirectToAction("ContactUsResponse", new { response = model });
}
}
public ActionResult ContactUsResponse(TTT.Models.ContactUsModel response)
{
return View(model)
}

MVC5 EF6 How to add confirmation screen with additional authentication before submitting data

Developing a new MVC5 project. I have my scaffolding in place for CRUD functionality but there is a requirement that when data is inserted or updated, an e-signature is required. Before data can be submitted to the database the user must be presented with a page asking them to enter their username and password again to confirm the data. If the username and password entered is valid and the username matches the currently signed in user, then the original data entered can be saved to its table (for example Member) and the e-signature information is saved to a separate table (ESignature). I'd appreciate any help on the best way to go about this - a view model combining Member and ESignature, or a reuse of the LoginViewModel from the Account controller to check the authentication, or an alternative approach? I need something that I can use across half a dozen controllers where e-signatures are required.
Alright maybe my approach is not the best but I will attempt.
My solution would be to create a CustomAttribute: AuthorizeAttribute and decorate all the actions which require Esignature. In your CustomAttribute implementation you will redirect to a controller action exactly similar to Login but with slight modification.
public class CustomAuthorize : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
var url = filterContext.HttpContext.Request.Url;
var query = url.Query;
if (query.Contains("g="))
{
var code = query.Split(new String[] { "g=" }, StringSplitOptions.None);
//You can create time sensistive token and validate it.
}
else
{
//Redirect User to a particular page
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary
{
{ "controller", "Account" },
{ "action", "elogin" },
{ "redirectUrl", url.AbsolutePath}
}
);
}
}
}
Then decorate for example Index() method with it.
[CustomAuthorize]
public ActionResult Index()
{
return View();
}
At first when you hit the Index() method then inside OnAuthorization method of CustomAuthorizeAttribute the else loop gets executed and re-directs you to a elogin method inside AccountController. This method is similar to the Login HttpGet method. While specifying the RedirectToResult I am specifying the redirectUrl path of the current page so when you successfully validate a user inside the elogin method then with the help of redirectUrl we can come back.
[AllowAnonymous]
public ActionResult ELogin(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
return View("Login");
}
//
// POST: /Account/Login
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ELogin(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindAsync(model.UserName, model.Password);
if (user != null)
{
await SignInAsync(user, model.RememberMe);
var url = String.Format("{0}/?g={1}", returnUrl, "HashCode");
return RedirectToLocal(url);
}
else
{
ModelState.AddModelError("", "Invalid username or password.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
The only difference in the HttpPost ELogin method is that before doing RedirectToLocal I append /g=HasCode. Note: Here you can append your own logic to create a time sensitive hash. When we get redirected to our home page then we can inspect inside our OnAuthorization Method if the url contains g=HashCode then don't redirect to Login Page.
This would be very basic idea on how you can approach to force users to re-sign in whenever they hit specific controllers. You will have to do additional security checks and be careful in what you are exposing via url.

Redirect to action with parameters always null in mvc

When I tried redirect to action, the parameter is always null when I received ? I don't know why this happening like these.
ActionResult action1() {
if(ModelState.IsValid) {
// Here user object with updated data
redirectToAction("action2", new{ user = user });
}
return view(Model);
}
ActionResult action2(User user) {
// user object here always null when control comes to action 2
return view(user);
}
And with this I've another doubt. when I accessed action with route, i can get values only by RouteData.Values["Id"]. the values routed doesn't send to parameter.
<a href="#Url.RouteUrl("RouteToAction", new { Id = "454" }> </a>
Here Am I miss any configure ? or anything I miss.
ActionResult tempAction(Id) {
// Here Id always null or empty..
// I can get data only by RouteData.Values["Id"]
}
You cannot pass complex objects in an url like that. You will have to send its constituent parts:
public ActionResult Action1()
{
if (ModelState.IsValid)
{
// Here user object with updated data
return RedirectToAction("action2", new {
id = user.Id,
firstName = user.FirstName,
lastName = user.LastName,
...
});
}
return view(Model);
}
Also notice that I have added the return RedirectToAction instead of only calling RedirectToAction as shown in your code.
But a much better approach is to send only the id of the user:
public ActionResult Action1()
{
if (ModelState.IsValid)
{
// Here user object with updated data
return RedirectToAction("action2", new {
id = user.Id,
});
}
return view(Model);
}
and in your target action use this id to retrieve the user from wherever this user is stored (could be database or something):
public ActionResult Action2(int id)
{
User user = GetUserFromSomeWhere(id);
return view(user);
}
Some alternative approaches (but one I don't recommend or use) is to persist the object in TempData:
public ActionResult Action1()
{
if(ModelState.IsValid)
{
TempData["user"] = user;
// Here user object with updated data
return RedirectToAction("action2");
}
return view(Model);
}
and in your target action:
public ActionResult Action2()
{
User user = (User)TempData["user"];
return View(user);
}

How can I implement multiple forms using a single view?

I am having a scenario where I need to implement two forms using a single view... There will be a home page having a form each for LogIn and SignUp (similar to Facebook homepage). I created a view for my home page (Index.cshtml) that contains the razor code for both my forms.
[#using (Html.BeginForm("LogIn", "Home", FormMethod.Post))]
[#using (Html.BeginForm("SignUp", "Home", FormMethod.Post))]
However, upon clicking the 'Log In' button for LogIn form or clicking 'Sign Up' button for SignUp form, the runtime throws an error basically saying that I still need to create views for both LogIn and SignUp actions, even though I have already implemented the HTML forms in my index.cshtml
[NOTE: I am not using ASP.NET membership provider. And this question is generally for two forms, can be any two forms.]
So my question is: Do I really need to create two more views named LogIn.cshtml and SignUp.cshtml? Won't this cause code duplication? I'm quite new to MVC 4 and I hope you understand what I'm trying to do here, so all I want to know is whether there is any other way to implement this? (jQuery, AJAX or something)
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpGet]
public ActionResult LogIn()
{
return View();
}
[HttpPost]
public ActionResult LogIn(Account acc)
{
// some code
return View();
}
[HttpGet]
public ActionResult SignUp()
{
return View();
}
[HttpPost]
public ActionResult SignUp(Account acc)
{
// some code
return View();
}
}
You could specify the view you want to be returned:
[HttpGet]
public ActionResult SignUp()
{
return View("LogIn");
}

Preserving model in ASP.NET MVC 4

I have an ASP.NET MVC 4 app. I'm relatively new to ASP.NET MVC 4. Currently, I'm trying to build a basic Task list app.
public ActionResult Create()
{
var model = new TaskModel();
return View("~/Views/Task.cshtml", model);
}
[HttpPost]
public ActionResult Create(TaskModel model)
{
if (model.TaskName.Length == 0)
{
// Display error message
}
else
{
// Save to database
// Write success message
}
return View("~/Views/Task.cshtml", model);
}
If there is an error, I display an error message on the screen. My problem is, the previously entered values in the view are not shown. The entire view is blank.How do I preserve the values in the view in this case?
Thank you!
I use TempData for this.
public ActionResult Create()
{
var model = new TaskModel();
TempData["task"] = model;
return View("~/Views/Task.cshtml", model);
}
[HttpPost]
public ActionResult Create()
{
var task = (TaskModel)TempData["task"];
UpdateModel(task);
if (model.TaskName.Length == 0)
{
// Display error message
}
else
{
// Save to database
// Write success message
}
TempData["task"] = task;
return View("~/Views/Task.cshtml", model);
}
MVC works different than WebForms, since there is no concept of 'controls', you have to preserve the state yourself. Another option if you don't want to use TempData is to use an LosFormatter to Serialize your controls into a hidden HTML field. This would replicate the functionality of ViewState in ASP.NET WebForms