How to transfer data from a view to a method? - asp.net-mvc

There is a Customer controller, it has the DeleteCustomer action method.
public class CustomerController : Controller
{
[HttpGet]
public IActionResult Index()
{
IEnumerable<CustomerViewModel> customers =
_customerRepository.GetAllCustomers().Select(s => new
CustomerViewModel
{
CustomerId = s.CustomerId,
Name = s.Name,
Adress = s.Adress
});
return View("Index", customers);
}
[HttpPost]
public IActionResult DeleteCustomer(int id)
{
_customerRepository.Delete(id);
return LocalRedirect("~/Customer/Index");
}
}
Here is the link, when clicked, the action method should work, the Id of the user I want to delete should fly into the method. But he writes an error 405. Somewhere I was mistaken I can not understand exactly where. I would be grateful for your help. I think the tag "a" is a Get request. Use #Html.ActionLink()?
<a asp-action="DeleteCustomer" asp-route-id="#item.CustomerId">Delete</a>

The problem is that DeleteCustomer only responds to POST, but HTML links are always requested via GET. However, DeleteCustomer should require a POST, so don't change that. Instead, you need to use a form like:
<form asp-action="DeleteCustomer" method="post">
<input type="hidden" name="id" value="#item.CustomerId" />
<button type="submit">Delete</button>
</form>
Then, if you want the button to look like a link, you can simply style it to look that way. If you're using Bootstrap, you can just apply the btn-link class to it.

Related

MVC HTTP Post input return null

Controller:
public ActionResult MyController()
{
ViewBag.DateNow = DateTime.Now.ToString("yyyy-MM-dd");
}
[HTTPPost]
public ActionResult MyController(string fromDate)
{
ViewBag.DateNow = fromDate;
}
View:
#using (Html.BeginForm("MyController", "Account", FormMethod.Post))
{
//datepicker class: bootstrap-datepicker.js
<input id="fromDate" type="text" class="datepicker" />
<buttontype="submit" value="Search" class="btn btn btn-primary">
Search
</button>
}
What I'm trying to achieve is before POST the data that pass into ViewBag.DateNow is the current date and it successfully bring in to the view. However when I'm trying to fill up the input form with (eg: 2016-05-10) and click on the Search button. But seems like the fromDate string return NullReferenceException. I'm trying out with some solution online but I still can't get it right and that's why I decided to get this posted up. Thanks in advance!
For this to work properly you need to specify the name attribute in your textbox. It needs to be the same value as the input variable in your HTTP post action method, namely fromDate. Currently the id attribute is set to fromDate:
<input id="fromDate" name="fromDate" type="text" value="#ViewBag.DateNow" />
If you do not specify this name attribute then when you post your form fromDate will always be null. Specifying it like above will make sure that fromDate will always have a value (if entered).
I want to go a bit off-topic here, I would like to suggest that you make use of view models for your form submissions. Instead of having individual input variables in your action method you can just have your view model as input parameter.
I wrote an answer as to what view models are here, please go and read it if you have the time:
What is ViewModel in MVC?
Working on your example, I would have a view model that contains just one property, namely FromDate. FromDate will contain the value in your textbox. It is setup as a string because you want to pass it a formatted date value:
public class TestModel
{
public string FromDate { get; set; }
}
This value will be set in your HTTP get action method and the view model will be sent to the view:
public ActionResult Index()
{
TestModel model = new TestModel();
model.FromDate = DateTime.Now.ToString("yyyy-MM-dd");
return View(model);
}
In your view you will accept this view model and create the form accordingly:
#model WebApplication_Test.Models.TestModel
#using (Html.BeginForm())
{
#Html.TextBoxFor(m => m.FromDate)
<button type="submit">Search</button>
}
When you submit this form, you need an HTTP post action method to handle the submission. Because the view is bound to the view model, the action method will accept it as an input parameter:
[HttpPost]
public ActionResult Index(TestModel model)
{
// Do what you need to do
string date = model.FromDate;
return View(model);
}
Your way of doing it is also correct. I have just shown you an alternative way to do it. Some day you might have a huge form with many input values, then my approach will be 'cleaner'.
Try this:
1) Replace with [HttpPost] instead of [HTTPPost]
2) You should add name=" " for input like this:
<input id="fromDate" name="fromDate" type="text" class="datepicker" />

ASP.NET MVC - redirect after form submit

I have a ASP.NET MVC website and a "Configuration" view with a form.
When I submit the form, I would like to do some stuff and then Redirect to my "Initialization" ViewResult... How to do it ?
My form :
#using (Html.BeginForm("Save", "Home", FormMethod.Post, new { id = "Config" }))
{
// Some fields
<input type="submit" value="Save" />
}
then, the "Save" action :
[HttpPost]
[ValidateAntiForgeryToken()]
public async Task<RedirectToRouteResult> Save(Config websiteConfiguration)
{
// Do some stuff
bool ok = await myMethod();
if(ok)
{
return RedirectToAction("Initialization");
}
}
I tried other possibilities but I don't manage to get it work...
Up, I still have the problem...
Not sure if this issue was with an earlier version of MVC, but I have often forgotten that the [HttpPost] label may be placed above an ActionResult in the controller and not just above a JsonResult.
So the simplest MVC-style answer would be just use Html.BeginForm and post to the ActionResult (with the [HttpPost] attribute), wherein you execute your logic, then call RedirectToAction at end after you have handled the post controller side.
This seems far easier than all the client-side fiddles, e.g. window.location.href = '' etc...
This is what your Form Post method should look like
<HttpPost>
<ActionName("Respond")>
Function Respond_post(viewModel As FormsRespondModel) As ActionResult
viewModel.form.formId = Guid.Parse(Request("formId"))
viewModel.form.loadForm(Guid.Parse(Request("formId")))
If (viewModel.form.formNotifications.onSuccess = "redirectOnSuccess") Then
Return Redirect(viewModel.form.formNotifications.redirectUrl)
End If
Return RedirectToRoute("form_finished")
End Function
Try this :
<input id="btnSave" name="btnSave" type="submit" value="Save" onclick="window.location = '#Url.Action("Action_Name", "Controller_Name")'; return false;" />

Using webforms in MVC

I am learning MVC, following THIS tutorial. (link will take you directly to where i'm stuck). so far I have learnt, there's a controller for every view. Now i have to take input from user through web entry form as mentioned in tutorial. In my project, i have a controller named Default1 and i can run it as localhost:xyz/Default1/Index. it runs perfect.
Then i created a new Controller, named Default2 and bound it to some view to display some data, and it worked perfect as localhost:xyz/Default2/Displaycustomer. the customer information was static (hard coded). and controller is as:
public ViewResult DisplayCustomers()
{
Customer cobj = new Customer();
cobj.Code = "12";
cobj.Name = "Zeeshan";
cobj.Amount = 7000;
return View("DisplayCustomers",cobj);
}
Now i have to take input from User, regarding cutomer iformation, using html page as mentioned in tutorial. so i tried adding a new webform under view folder, and and modified my controller as:
[HttpPost]
public ViewResult DisplayCustomers()
{
Customer cobj = new Customer();
cobj.Code = Request.Form["Id"].ToString();
cobj.Name = Request.Form["Name"].ToString();
cobj.Amount = Convert.ToDouble(Request.Form["Amount"].ToString());
return View("DisplayCustomers",cobj);
}
My Question is: How can i make my project stared, so that it takes input first, and then displays it, using above controller? Did i add the webform at right location? What would be the link to run it? i tried localhost:xyz/Default2/entryform etc. but failed.
(in my entryform.aspx, i have mentioned form action="DisplayCustomer" )
It sounds like what you're missing is an action to just display the form. In otherwords, you just need an action to display a form. That form's POST action should reference your controller's DisplayCustomers action.
So in your controller code:
public class CustomerController : Controller
{
[HttpGet]
public ViewResult New()
{
return View("NewCustomer"); //Our view that contains the new customer form.
}
// Add your code for displaying customers below
}
And in your view, you have code like this
#using(Html.BeginForm("DisplayCustomers", "Customer")) {
<!-- Add your form controls here -->
}
Notice that I'm using the version of the BeginForm helper that specifies the action method and controller to call. This will write the form tag to post back to your DisplayCustomers action. Here is the equivalent HTML:
<form method="POST" action="/Customer/DisplayCustomers">
You would then access your form using the URL http://test.server/Customer/New.
This may not be the best example in the world...but this will at least get you rolling..
url would be:localhost:1234/Home/Customer
the controller
public ActionResult Customer()
{
return View();
}
[HttpPost]
public ActionResult Customer(FormCollection frm)
{
var name = frm["name"].ToString();
var address = frm["address"].ToString();
ViewBag.Name = name;
ViewBag.Address = address;
return View();
}
The view
<div>
#using (Html.BeginForm())
{
<input type="text" name="name" id="name" />
<input type="text" name="address" id="address"/>
<input type="submit" name="submit" value="submit" />
<input type="text" name="namedisplay" value='#ViewBag.Name'/>
<input type="text" name="addressdisplay" value='#ViewBag.Address'/>
}
</div>

Calling Function upon field change in MVC

I have a entity called WorkOrder which gets assigned to an Employee.
I want send an email notification when the workorder has been asigned. This can happen on my MVC Create or Edit Action (POST).
The problem i have is i have to do checks to see if the value has changed in the Edit to determine if i should send an email.
Is there a better place to call the SendEmail Function, like in the Entity Model itself?
If you are talking about posting from a view, you could create and bind the existing value to a hidden field in your form when loading the view. Then, on the POST to your action you can check to see if the value from the field is different from the one that is on the hidden field.
Example of View:
#using (Html.BeginForm("MyAction", "MyController")
{
#Html.HiddenFor(m => m.CurrentValue)
#Html.TextBoxFor(m => m.Value)
<input type="submit" value="submit" />
}
Example of Action GET
public ActionResult MyAction()
{
var viewModel = GetModelFromSomeWhere();
viewModel.CurrentValue = viewModel.Value;
return this.View(viewModel);
}
Example of Action POST
[HttpPost]
public ActionResult MyAction(ViewModel model)
{
if (model.Value != model.CurrentValue)
{
// It has changed! Send that email!
}
}

FormsCollection in Mvc Controller method - any other way of accessing?

I have a form which I want to post to ensure the page refreshes on posting the data (not the ajax way). The problem is really I only want to post the Id of the record and extract that in the controller method. I'm finding that the form is posting everything (I might not be able to resolve that since the same form is used for updating). But I'd like to be able to have the variable pop into the parameter of controller method rather than extracting from the FormCollection. I've tried the various parameters below, but all are being passed null. Any idea what the problem is?
I have the following in my controller method:
public ActionResult Delete(FormCollection collection)
{
var idToDelete = collection["Current.CommissionStructureId"].ToInt32();
}
// tried the following but none of them bind
public ActionResult Delete(int? Current_CommissionStructureId, int? CommissionStructureId, int? Id, int? id)
{
// none of the above are binding (set to null)
}
You should use HttpPost only for deleting of records
#using (Html.BeginForm()) {
<input type="hidden" name="CommissionStructureId" value="#item.CommissionStructureId" />
<p>
<input type="submit" value="Delete" />
</p>
<p>
#Html.ActionLink("Back to List", "Index")
</p>
}
[HttpPost]
public ActionResult Delete(int CommissionStructureId)
{
CommissionStructure commissionStructure = db.CommissionStructures.Find(CommissionStructureId);
db.CommissionStructures.Remove(commissionStructure);
db.SaveChanges();
return RedirectToAction("Index");
}
When your form value is named Current.CommissionStructureId the default modelbinder will bind it only to a class parameter called Current with a property called Id.
So your options are
Create a small class with one property Id and use it as your parameter type
or
Write a custom modelbinder

Resources