I'm having a real problem trying to articulate this seemly simple problem.
I have a single view that contains a FORM with a few search fields at the top of the view and the results of that search get shown on the same view after submitting the form.
I have a single HTTPGET controller method that takes the form fields as parameters and IF it was submitted by a user it will pass the model back to the view with the results to be shown and pre-populate the search form with what they filled out.
How can I tell if the page was loaded with default parameters vs. someone actually submitted the form.
What's the best way to accomplish this?
If I am understanding your question correctly then I think you need to consider the HttpGet attribute:
https://msdn.microsoft.com/en-us/library/system.web.mvc.httpgetattribute(v=vs.118).aspx
and the HttpPost attribute:
https://msdn.microsoft.com/en-us/library/system.web.mvc.httppostattribute(v=vs.118).aspx
Lets say you have a create method. The Http method would look like this:
[HttpGet]
public ActionResult Create()
{
}
and the post method would look like this:
[HttpPost]
public ActionResult Create(Person p)
{
//Logic to insert p into database. Could call an application service/repository to do this
}
RedirectToAction solve the problem.
you can go back to the get method after submited data and populate the view with default values
[HttpGet]
public ActionResult Create()
{
// fill model to default data
return view(model);
}
[HttpPost]
public ActionResult Create(Person p)
{
//do your stuff save data
return RedirectToAction("Create");
}
or
[HttpPost]
public ActionResult Create(Person p)
{
if(...)
{
//do your stuff any logic
return RedirectToAction("Create");
}
//do your stuff
return view(...);
}
Related
I have got a submit button for a form, this controller actionresult method gets called when the button is pressed. Depending on the return of the _shortUrlProcessor.CreateShortURL method. I want to either display a message in red or a create a link under the mentioned submit button. What is the proper way of handling this in MVC? (see comments in code for more clarification as well)
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ShortenURL(ShortURLModel model)
{
if(ModelState.IsValid)
{
if(_shortUrlProcessor.CreateShortURL(model.originalURL, model.shortURL))
{
ViewBag.ShortenURLSuccess(model.shortURL); //< ---- send as a localhost:port/model.shortURL link
}
else
{
ViewBag.ShortenURLSuccess("Could not create link"); //<----send as a text label (which would be shown in something like a <div/>)
}
}
return View();
}
Putting this in the view is the way to go, and here is an example using the viewbag approach:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ShortenURL(ShortURLModel model)
{
if(ModelState.IsValid)
{
if(_shortUrlProcessor.CreateShortURL(model.originalURL, model.shortURL))
{
ViewBag.ShortenURLSuccess=true;
ViewBag.ShortenURL=model.shortURL;
}
else
{
ViewBag.ShortenURLSuccess=false;
}
}
return View();
}
And then in the view:
#if (ViewBag.ShortenURLSuccess)
{
Go here
}
else
{
<div class="error">Could not create link</div>
}
If you need more information for the url or the message, you can put those in viewbag variables as well.
it is worth noting that a more popular way to do this is with model binding, but this approach works fine for what it is. You can use the submitted model and move away from the viewbag to be a bit more efficient.
I return the View from my controller start_run1 to a view start_run1
public ActionResult start_run1(int? id) { ....
return(View);
}
I get 404 page not found, even if I try using absolute paths etc etc.
if I add the code it finds the page but model data or ViewBag data doesn't get passed.
public IActionResult start_run1()
{
return View();
}
I have another similar controller function which works without doing this.
Any ideas, Ive tried everything.
When I load the default page (http://localhost/MVCP/Home/index) it loads correctly, whereas when I load another view (http://localhost/MVCP/Home/Create) it doesn't load. How can I fix this?
My Create action in HomeController:
[HttpGet] [ActionName("Create")] public void Create() { }
Q: Do you have an action in your HomeController called Create?
A: Yes, [HttpGet] [ActionName("Create")] public void Create() { }
Your action return value is void and probably you even didn't write anything in response. change the signature of action to have an ActionResult as return a View.
public ActionResult Create()
{
return View();
}
To learn more:
Adding a View
in Getting Started with ASP.NET MVC 5 Series.
May be there is no view you have created so far and it seems your controller are inside area folder so have u checked your routeing too.
I think your Action should return ActionResult or ViewResult but certainly not "void" as you have written currently.
and also you should write
return view();
in Create action
I am passing an model from one controller method to another controller method to collect all the values to model fields. I am doing as shown below
[HttpPost]
public ActionResult A(Model m, string s)
{
if (ModelState.IsValid)
{
if (m.l == null || m.k == null)
{
//Do something.
}
else
return View("B", m); // this is where by debug point comes...
}
return View(m);
}
public ActionResult B(Model m)
{
return View(m);
}
[HttpPost]
public ActionResult B(Model m, string s)
{
if (ModelState.IsValid)
{
if (m.p == null || m.j == null)
{
//do something
}
else
{
// do something and redirect to somewhere else
}
}
But as I have shown the debug point comes here as shown below.
return View("B", m);
This should hit the Controller method "B" But the problem is It does not hit the controller method "B". But it shows the view for the Controller method "B" So, I am confused about this problem. And I can not see the values for (l,k) in the httppost of method "B". What is the reason for this.
I want to know that, I am doing this right or wrong. If I am doing this wrong can you please explain on this for a bit. Can someone who is good at MVC help me.
Thanks in advance.
That code -- return View("B", m) -- actually doesn't redirect to the action B, it just renders the view B with the given model. If you want to execute the action, then you should use:
return B(m);
You should not call an action from another action. The view RESULT is executed after the controllers action method (the top one) is executed . Calling on action from another is not intended and can provide multiple pathways to the same action method. Your controller purpose is to orchestrate data. If you think multiple methods should be called then you should break those apart into other facade classes or service layer classes that each controller that needs it will request it or aggregate this information into a domain object that you then populate a view model from
If any of this isn't clear I'll clarify further.
Either call several repository methods to get the data and populate into a view model
Or
Use a parent view and call RenderAction from within the view to emit other controllers data
Or use RenderPartial to use your parent views object to pass to each child view to render it's portion but I like the RenderAction more unless all the data makes sense to be available to your top level view's view model.
Or
Call a facade layer class from your controller that in turn gets data from various locations, does xyz and returns it to the controller who then populates a view model from this data.
Try something like this,
[HttpPost]
public ActionResult A(Model m, string s)
{
if (ModelState.IsValid)
{
if (m.l == null || m.k == null)
{
//Do something.
}
else
RedirectToAction("B", m); // check this
}
return View(m);
}
public ActionResult B(Model model)
{
return View(model);
}
Try the below code. It should work. This is an alternative to the answer of #dbaseman
[HttpPost]
public ActionResult A(Model m, string s)
{
if (ModelState.IsValid)
{
if (m.l == null || m.k == null)
{
//Do something.
}
else
{
TempData["tempModel"]=m; //cannot pass a model in a redirect method. so store it in a tempdata object.
return RedirectToAction("B"); // redirect to action method B
}
}
return View(m);
}
public ActionResult B()
{
Model model= new Model();
if(TempData["tempModel"]!=null)
model=(Model)TempData["tempModel"];
return View(model);
}
My controller has 2 actions:
Results()
Index()
I want to share the view named index.aspx between these 2 actions.
See my previous post for more information
When I build my link to the page, I assume I cannot send it to Index action as it is expecting a FormCollection type and hence I create a Results action
public ActionResult Results(ClientSearch data, int? page)
{
FormCollection collection = new FormCollection();
collection.Add("FNAme", data.FName);
collection.Add("Lane", data.Lane);
collection.Add("Zip", data.Zip);
collection.Add("Phone", data.Phone);
return Index(page, collection);
}
Not sure I completely understand your question, but if you want to use the same View on different ActionResults, you can:
public ActionResult One() {
// do stuff
return View("Index", myModel);
}
public ActionResult Two() {
// do stuff
return View("Index", myOtherModel); // Same View
}
Just make sure you are providing the same Type for the View (if the View needs a Type at all).
Of course you can. It's up to controller to decide how to react and what view to serve back.
Now that I've read your question to the end :)), well, you can get away with two actions of the same name. The one will be accepting GET commands (initial load of the page), the other will be serving POST requests, perform the necessary action and redirect back to the same View.
public MyController
{
[AcceptVerbs (HttpVerbs.Get)]
public ActionResult Index ()
{
return View ();
}
[AcceptVerbs (HttpVerbs.Post)]
public ActionResult Index (ClientSearch data, int? page)
{
// Process form post
return RedirectToAction ("Index");
}
}