How can I inspect the post data that are being submited In my application? I want see If there are any data In the input fields when the post are submited.
Html:
<div id="addBox" style="display: none; margin-top: 10px;">
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-group">
#Html.Label("Descrption", "Att göra"):
#Html.TextBox("Description", null, new { id = ViewBag.ListContainerID })
<input type="submit" value="Ok" class="btn btn-default" />
</div>
}
</div>
Controller:
[HttpPost]
[ActionName("Details")]
public ActionResult AddTask(FormCollection values)
{
var id = values["id"];
var desc = values["Description"];
/*Task task = new Task
{
Description = desc,
ListContainerID = id
};
db.Tasks.Add(task);
db.SaveChanges();*/
return RedirectToAction("Details");
}
I have tried to set a breakpoint beside the id and desc, but can't find the information about what the input field contains.
In PHP you can use var_dump($_POST) to see information about the POST-data after you hit a submit-button. I want to do the EXACT same thing in ASP.NET
No, you don't want to do that.
Visual Studio has a great debugger that you can use. Set breakpoints and inspect the relevant variables. That way you don't have to change your code when debugging, and you can't forget to remove it afterwards.
You could use the ViewBag to transfer variables from your controller to your view:
// Set in Controller:
ViewBag.TestingVariable1 = values["Foo"];
// Render in View:
#ViewBag.TestingVariable1
Still, this is not recommended. You're changing your application to debug, which is never advisable.
If you insist, look at Response.Write():
Why haven't you added the parameters of the Html.BeginForm(). It should be:
Html.BeginForm("AddTask","ControlerName...",FormMethod.Post)
{}
To check the submit values, you could use ajax and do an async call of the controller method and use alerts/logs to check/print the values (jquery).
Related
Caution, before You read the rest
This question is not about POST method, redisplaying view with submited form or binding input values to controller method parameters. It's purely about rendering the View using html helper (HiddenFor or Hidden - both returns the same).
I created a simple hidden field using HiddenFor helper
#Html.HiddenFor(m => m.ProductCode)
and my problem is that value for this hidden field is rendered as null:
<input id="productCode" name="productCode" type="hidden" value/>
Even if I set it when instantiating a model and of course it's confirmed with debugging (it always has a value).
So instead it should look like this:
<input id="productCode" name="productCode" type="hidden" value="8888888"/>
Because I know there are some questions like this one (actually all of them refer to changing form values during form POST) I included list of things I tried already. My code is right below this section which I belive to be essential.
So far I tried:
ModelState.Clear() everywhere possible - cause as we know the value from ModelState is first place where it looks for the value. NO EFFECT which I expected, cause my ModelState is empty (my case is not about changing value during POST in controller as in many questions like that), so it should take value from my view model.
Not using HiddenFor helper, but pure html instead. WORKS, but its just workaround, not an answer to the problem.
Duplicating line with helper in view as follows:
#Html.HiddenFor(m => m.ProductCode)
#Html.HiddenFor(m => m.ProductCode)
PARTIALLY WORKS Produces first input as value/> and second as value="8888888"/> which indicates that there is probably something that hides initial property value. Anyway, I found nothing in ViewData at any point, nor in query string. Obviously I can't accept it this way, no explonation needed I guess.
Changing name of the property. Originally it was ProductCode. I changed it to productCode, ProdCode, ProductCodeasd, etc. and all of these WORKS. Again, it looks like there is something that hides/updates the value, but again - 100% sure there is no JS or anything else doing it. So still no answer found - just workaround again.
Explicitly setting the value for HiddenFor: #Html.HiddenFor(x => x.ProductCode, new {Value = #Model.ProductCode}). NO EFFECT, renders the same way.
Using #Html.Hidden instead of #Html.HiddenFor. NO EFFECT, with name set as ProductCode it renders the same way.
One more thing I found interesting. Reading html with Display page source in Chrome [ctrl+U] shows that value is valid value="8888888"/>, but in DevTools it's still value/> and of course submitting the form passes null to Controller method.
Model
public class Product
{
public string Description { get; set; }
public int Quantity { get; set; }
public string ProductCode { get; set; }
public string ImageUrl { get; set; }
public Product(string desc, string productCode, string imgUrl)
{
Description = desc;
ProductCode = productCode;
ImageUrl = imgUrl;
}
}
View
#model Product
#using (Html.BeginForm("UpdateCart", "Cart"))
{
<div class="row pad10">
<div class="col-sm-6 text-center">
<img src="#Model.ImageUrl" width="300" height="300" />
</div>
<div class="col-sm-6 text-justify">
<p>#Model.Description</p>
<div class="row padding-top-2">
<div class="col-sm-6">
<label>#CommonResources.Quantity: </label>
</div>
<div class="col-sm-4">
#Html.TextBoxFor(m => m.Quantity, new
{
#class = "form-control",
#data_val_required = CommonResources.FieldRequired,
#data_val_number = CommonResources.ValidationNumber
})
#Html.ValidationMessageFor(model => model.Quantity, "", new { #class = "text-danger" })
#Html.HiddenFor(m => m.ProductCode)
</div>
</div>
</div>
</div>
<div class="text-center col-xs-12 padTop20 padBottom20">
<input type="submit" value="Submit" class="whtBtn pad" />
</div>
}
Controller
The view is returned from controller with RedirectToAction as follows:
ValidateAndProceed -> ResolveNextStep (here redirection occurs) -> ShowProduct
public ActionResult ValidateAndProceed()
{
var order = Session.Current.Order;
var lang = LangService.GetSelectedLanguage();
var invoice = Session.Current.CurrentInvoice;
var localCurrency = Session.Current.LocalCurrencyInfo;
List<CheckoutValidationFieldError> errors = new List<CheckoutValidationFieldError>();
errors = ValidationService.ValidateAddress(order);
if (errors.Count > 0)
{
return RedirectToAction("InvalidAddress", "Address", new { serializedErrors = JsonConvert.SerializeObject(errors) });
}
return ResolveNextStep(order, invoice);
}
public ActionResult ResolveNextStep(IOrder order, IInvoice invoice)
{
if (OrderService.ShowProductView(order, invoice))
{
return RedirectToAction("ShowProduct");
}
return RedirectToAction("Summary");
}
public ActionResult ShowProduct()
{
Product model = ProductService.GetProduct(Session.Current.CurrentInvoice);
return View("~/Views/Product.cshtml", model );
}
Finally, what can cause such a weird behavior? I've already ran out of options. Maybe anyone had problem like mine before, would appreciate any clue on this case.
I debugged the whole process of rendering the view (got into .Net sources) checking every possible place that could make it fail and found nothing.
After #AndyMudrak and #Jeremy Lakeman comments I decided to try again to find JavaScript responsible for that behavior, but deeper than I did before. What I found was a really silly script where element Id is being concatenated from three strings what I didn't expect, cause it's really badly implemented. So finally - JavaScript is doing it and there is no bad behavior from framework etc.
Actually I am a bit disappointed (even if it's good to know this easy answer) cause it looked much more complicated than it really was and it took me hours to find out how simple it is :|
Thanks for comments, sorry for final simplicity.
I have two Create methods one decorated with HttpGet, and the other with HttpPost. I have a create view for the first one looking like this :
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<form action="/" method="post">
<input type="text" name="txt" value="" />
<input type="submit" />
</form>
The methods :
List<string> myList = new List<string> { "element1", "element2", "element3" };
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(string txt)
{
//myList.Add(Request.Form["txt"]);
myList.Add(txt);
return View();
}
I am simly trying to pass the data from my form on button to my second Create() and save it to myList.
I need some advice on how to make this work.
Once you've fixed your form (in that you're posting back to your application's default route (by default HomeController.Index() method) by sending the request to /, instead of your Create method), you are actually correctly adding the value to your list. The problem is, that value only stays for the current request.
To make things persistent, you need to consider a persistence layer in memory, in database, or in session. I've provided a full sample below that uses the session, which will give you a per-user list instance. Without this layer, your Controller is being routinely disposed of once the action has completed processing, and so the amends to your list are not persisted. This is the normal request lifecycle in ASP.NET and makes sense when you consider that your app is basically only ever dealing with 1 request at a time. It's important to note that making something static isn't a form of persistence per-se, in that its lifetime and reliability is indeterminable. It will appear to work, but once your application pool recycles (ie. the app is destroyed and reloaded in memory) you will have again lost all amends to your list.
I would suggest you read up on Session State to understand exactly what is going on below. In a nutshell, each application user / unique visitor to your site will be given a unique 'session ID', you can then use this session ID to store data that you wish to use on the server side. This is why, if you were to visit your Create method from separate browsers (or try Private mode) you will be maintaining two separate lists of data.
View (which also outputs the list to the user):
#model List<string>
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<ul>
#foreach(var str in Model)
{
<li>#str</li>
}
</ul>
#using (Html.BeginForm())
{
<input type="text" name="txt" />
<input type="submit" />
}
Controller contents:
public List<string> MyList
{
get
{
return (List<string>)(
// Return list if it already exists in the session
Session[nameof(MyList)] ??
// Or create it with the default values
(Session[nameof(MyList)] = new List<string> { "element1", "element2", "element3" }));
}
set
{
Session[nameof(MyList)] = value;
}
}
public ActionResult Create()
{
return View(MyList);
}
[HttpPost]
public ActionResult Create(string txt)
{
MyList.Add(txt);
return View(MyList);
}
Please use this:
#using (Html.BeginForm("Create", "Controller", FormMethod.Post)){
<input type="text" name="txt" value="" />
<input type="submit" />
}
Replace Controller with your Controller name.
Or simply use:
#using (Html.BeginForm()){
<input type="text" name="txt" value="" />
<input type="submit" />
}
When you call BeginForm() without any parameters it default to using the same controller/action used to render the current page.
I'm trying to call an ActionResult method from a web page form but I can't seem get the two items to connect.
The desired result is for the page to refresh and filter the model to display the required results.
Method in serversController.cs
The internal code works as intended when placed in ActionResult Index
[HttpPost]
public ActionResult activeServers()
{
// load the servers into local variable
var servers = from s in db.Servers
select s;
// filter out the archived servers
servers = servers.Where(s => s.archive.Equals(0));
return View(servers.ToList());
}
Button making the call
#using (Html.BeginForm())
{
<button name="activeServers" type="submit" value="activeServers" class="btn btn-default">Active</button>
}
Thanks is advance
Try to specify the action method, controller name (without the controller suffix) and the http method (it defaults to GET) in the BeginForm:
#using (Html.BeginForm("activeServers", "Servers", FormMethod.POST))
{
<button name="activeServers" type="submit" value="activeServers" class="btn btn-default">Active</button>
}
I have to allow the user to move to the next or previous form, I just need to save the model on navigation. Is there another way to pass back the model to the controller besides using submit? Since I need to redirect to other possible pages.
You could put your model object in the TempData collection on submit, redirect, then read it back out again. For example:
[HttpPost]
public ActionResult FirstForm(FirstFormModel model) {
TempData["TempModelStorage"] = model;
return RedirectToAction("SecondForm");
}
public ActionResult SecondForm() {
var firstModel = TempData["TempModelStorage"] as FirstFormModel;
// check for null, use as appropriate, etc.
return View(...);
}
More details here: http://msdn.microsoft.com/en-us/library/dd394711(v=vs.100).aspx
You may save the data asynchronously using jQuery ajax on those button click events.
Assuming your View is something like this
#using(Html.BeginForm("Save","Items"))
{
<div>
Name : #Html.TextBoxFor(s=>s.Name)
<input type="button" class="navigBtns" value="Prev" />
<input type="button" class="navigBtns" value="Next" />
</div>
}
And your script is
$(function(){
$(document).on("click",".navigBtns",function() {
e.preventDefault();
var _this=$(this);
$.post(_this.closest("form").attr("action"), _this.closest("form").serialize(),
function(res){
//check res variable value and do something as needed
// (may be redirect to another page /show/hide some widgets)
});
});
});
Assuming you have an action method called Save in your controller to handle the saving part.
Was given a neat article about this.
MVC Wizard Example
Basically this, you literally pass the name of the html button.
In the view form
<input type="submit" name="btnPrev" />
<input type="submit" name="btnNext" />
In the Controller
Controller
public ActionResult DoStuff(ModelClass mc,string btnPrev,string btnNext)
{
string actionString = "previousPage";
if(btnNext != null)
actionString = "nextPage";
return RedirectToAction(actionString,"Controller")
}
I have a search box in a Razor template:
#{
using (Html.BeginForm("Detail", "Book", FormMethod.Get))
{
#Html.TextBox("Id")
<input type="submit" value="Search" />
}
}
When I submit a search it goes to a url like:
~/Book/Detail?Id=1234
However I want it to format the url like so, just because I think it looks cleaner:
~/Book/Detail/1234
Which works perfectly fine because the controller method signature looks like this:
// GET: /Book/Detail/id
public ActionResult Detail(string id)
Model with TextBoxFor
I've tried a Html.TextBoxFor:
#model WebApplication.Models.SearchModel
#{
using (Html.BeginForm("Detail", "Book", FormMethod.Get))
{
#Html.TextBoxFor(m => m.Id)
<input type="submit" value="Search" />
}
}
Same result.
I think you want to take a look at the #Html.BeginRouteForm method, like in this question.
You use a GET request. This means that all parameters will appear in the url box.
I can't check now, but I suppose you could use these options:
The IIS url rewrite - http://www.iis.net/downloads/microsoft/url-rewrite
Url rewrite through a web.config - http://www.hanselman.com/blog/RedirectingASPNETLegacyURLsToExtensionlessWithTheIISRewriteModule.aspx
And a batch of stupid methods:
You can change your request to POST and then modificate the Url by the JS - Modify the URL without reloading the page
You can redirect the request
Also, did you try to add a personal routing for the search url?
Try using a model for the form submit and use #Html.TextBoxFor.
The answer was to add a new search action then redirect to the detail. This is nice because I can choose to do more when searching, such as returning a different view if the query has multiple matches.
//
// GET: /Book/Search?query=
public ActionResult Search(string query)
{
return RedirectToAction("Detail", new { id = query });
}
//
// GET: /Book/Detail/id
public ActionResult Detail(string id)
Razor:
#{
using (Html.BeginForm("Search", "Book", FormMethod.Get))
{
#Html.TextBox("query")
<input type="submit" value="Search" />
}
}