Controller returning PartialView overwriting entire View - c#

I'm POSTing and trying to re-load a partial view with the new data using Ajax like this:
Index.cshtml
<div id="left-column">
#Html.Partial("~/Views/Project/_ProjectList.cshtml", Model.ProjectList)
</div>
~/Views/Project/_ProjectList.cshtml
#using (Ajax.BeginForm("Create", "Project", new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "left-column"
}))
{
<h3>Create a new project</h3>
<div class="form-group">
<label for="new-project-name">Name</label>
<input type="text" class="form-control" id="new-project-name" name="Name" placeholder="Example" />
</div>
<button type="submit" class="btn btn-primary">Create Project</button>
Cancel
}
Then my Controller returns the PartialView after some db work:
[HttpPost]
public PartialViewResult Create(Project newProject)
{
db.Projects.Add(newProject);
db.SaveChanges();
var projectList = db.ProjectLists.SingleOrDefault(pl => pl.Id == 1);
return PartialView("~/Views/Project/_ProjectList.cshtml", projectList);
}
I would expect the _ProjectList partial view to load into the #left-column element with the new projectList passed in by the Controller, but instead, the entire View is being overwritten, so the entire body of the new HTML source looks basically like this:
<body>
<!-- all the stuff from the _ProjectList partial -->
</body>
It's worth noting that after the partial view returns, the URL reads /Project/Create, which I wouldn't expect.
I've included jquery-validate and jquery-validate-unobtrusive, and the console isn't showing any errors, so that shouldn't be the problem.
Any idea what's going on?

When using Ajax.BeginForm helper method to do ajax form posting, you need to include the jquery.unobtrusive-ajax.js file as well. This file has the code to handle the submit button click event and send the form asynchronously rather than doing the normal form submit.
If you do not include this file, the form submit will be normal. My guess is that you missed to include this file and hence missing the ajaxified form submit experience.
So make sure to load this file after jQuery
#Scripts.Render("~/bundles/jquery")
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
Here is the link to nuget page if you want to add this file via nuget package manager.

Benjy got it in a comment above. It was a jQuery version issue. I'm running 3.1.0, and jquery.unobtrusive-ajax stopped working with jQuery version 1.9.

Related

Form POST not doing anything

I have a webapplication made in ASP.NET Core (latest version) which needs to use a pop-up form where 1 value has to be filled in and then send it back to the controller to later use that value.
So the process is like this: Button > Click on button > Pop-up form pops up (Image: pop-up form which is a partial view) > Fill in value > Submit > Send result back to controller.
But whenever I press the submit button it sends me to a 400 error not found page. What could go wrong?
Here is the partial view pop-up form code:
#model IEnumerable<ApplicationName.Models.Moederblad>
#addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
#addTagHelper *, AuthoringTagHelpers
#Html.AntiForgeryToken()
<div id="element_to_pop_up">
<a class="b-close">x</a>
//Actionresult > Controller
#using (Html.BeginForm("Incassodatum", "Moederblads", FormMethod.Post))
{
<br />
<div class="row">
<div class="col-md-6">
<label for="Incassodatum">Incassodatum</label>
<input class="form-control" placeholder="Bijvoorbeeld: 19-02-2020" type="text" data-val="true" data-val-regex="Dat is geen geldige datum" data-val-regex-pattern="^(0[1-9]|[12][0-9]|3[01])[/](0[1-9]|1[012])[/](19|20)[0-9]{2}$, " id="Incassodatum" name="Incassodatum">
</div>
</div>
<div class="row">
</div>
<br>
<input name="__RequestVerificationToken" type="submit" class="btn btn-primary submit" value="Toevoegen" id="submit">
}
</div>
Here is the corresponding controller:
[HttpGet]
public ActionResult Incassodatum()
{
return View();
}
//Automatisch de datum van vandaag in het Incassodatum veld zetten nadat er op een knop is gedrukt
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Incassodatum(string Incassodatum)
{
string date= "";
if (ModelState.IsValid)
{
date = Incassodatum;
}
else
{
date = "Something went wrong.";
}
TempData["Incassodatum"] = $"{Incassodatum}";
return RedirectToAction("Index");
}
Then later I can use the tempdata to read out the value but its not working at all so that is actually useless for now.
I tried adding the [Route("Moederblads/Incassodatum")] property above the post.
I tried it in a normal view (So not a partial view) and there I could see the value with F12.
Tried changing object names as I thought it might conflict with other names.
Don't know what to do now. Any of you have a guess?
But whenever I press the submit button it sends me to a 400 error not found page.
A 400 error is a Bad Request. A 404 is a Not Found. As such, I'm not sure which you're actually getting here. However, based on the fact that you have an input with __RequestVerificationToken as the name, and you're using it wrong at that, I'm leaning towards the 400.
Since you're trying to use this input as a button, you've set a value on it to apply that text to the button. However, that's going to actually post that value for __RequestVerificationToken, and it's not a valid token. As such, you're going to always get a 400 Bad Request because of the failed request verification.
The request verification token should be on a hidden input, so the simplest solution is to remove the name from that button and add a hidden input specifically for the request verification token: #Html.AntiForgeryToken().
Even better would be to use the built-in FormTagHelper instead, which automatically takes care handling antiforgery tokens:
<form asp-action="Incassodatum" asp-controller"Moederblads" method="post">
...
</form>
Finally, while it doesn't technically effect anything, using input for buttons is an anti-pattern that should be avoided. Use <button type="submit"> instead.
Was something very easy in the end: I just had to delete the: [HttpPost] tag above the method and the [HttpGet] method as it did nothing in the end. After that it hit my break point and could verify that the value is coming through fine :)

How do I Return my View and call a btn function on it's form?

I have a Controller myCustomers with a View.
The controller has two useful ActionResults; namely loadDataTotbl and CreatePDF.
(Filestream with Itextsharp).
loadDataTotbl loads the View fine which is simply a db obj via LINQ.
The View has a table in a form with some elements and a create PDF button e.g.:
#using (Html.BeginForm("CreatePDF", "myCustomers", FormMethod.Post))
{
<form>
<table>
#foreach (var cn in Model)
{
<input type="text" value="#pn.CustomerName" name="cNameVal" />
}
<input type="submit" value="Download the PDF" />
</table>
</form>
}
It works fine. When I hit the button, PDF gets created.
How do I create the PDF but hide/bypass this view? Please note my View has to remain as I strip it's headers and values and use them in CreatePDF action to create and design my PDF.
Do I need partial view? How would it work here?
I don't think I can hide views if they have data I need.
How do I do this?

MVC .NET Refresh (Update) PartialView witout AJAX

I have a page with partial view that contains DevEx ComboBox with Add button and DevEx GridView ( I omitted GridView code). Page is showing properly with that partial view, only I have a problem with refreshing it.
//_ProductAppsGridViewPartial
<div class="form-horizontal">
<h4>Apps</h4>
#using (Html.BeginForm("AppsGridViewPartialAddNew", "Products", new { ProductID = ViewBag.ProductID }))
{
<div class="form-group">
<h5>Add new App:</h5>
#Html.DevExpress().ComboBox(settings =>
{
//..do some settings for ComboBox - some code omitted
settings.Properties.ValueField = "ApplicationID";
settings.Properties.TextField = "Name";
}).BindList(Model.AppsNotInProduct).GetHtml()
<input type="submit" value="Add" class="btn btn-default" />
</div>
}
</div>
I have action on my controller that adds selected app in database and returns a PartialView with the same (but refreshed) model, but response shows only that partial View. Here is a part of Controller's action that returns PartialView after updating database:
public ActionResult ProductAppsGridViewPartialAddNew(int ProductID)
{
//....update DB code - WORKS FINE
..
var model = GetProductAppsPartialModel(ProductID);
ViewBag.ProductID = ProductID;
ViewBag.CanEdit = true;
return PartialView("_ProductAppsGridViewPartial", model);
}
Is it possible to refresh a partial view wihout AJAX, maybe something i wrote above? So the main problem here is that i get new page showing only a partial view.
To refresh part of a page you will need to use ajax to replace only the needed content. You will also need to use JavaScript to re-render the HTML contained in the partial. MVC comes with some ajax helpers or you can do it yourself with jquery. At the moment the action result is returning the partial as requested but the browser is being told it is receiving a whole new page and is displaying as such.
Adding this link to Microsoft ajax to show some of your options.
I would use jquery and do this yourself. Also try to remember that mvc is a server side framework to help you return http messages to the browser. You are trying to manipulate things client side. Live client side updates always need ajax to get data. Replacing items in the DOM needs some form of JavaScript. Libraries like jquery make this a lot easier. Have a look at jquery ajax here.
I think you need to try this code.
Note here we need to keep ajax call for update the partial view
#using (Ajax.BeginForm("ActionName", "Controller", new { model = #Model.ID },
new AjaxOptions
{
OnSuccess = "onSuccessRefresh "
}))
{
<table>
<td>
</td>
<td> <input type="button" value="AddValue" /> </td>
</table>
}
Handle the code onsuccess event using jquery:-
function onSuccessRefresh {
// refersh your page or table
}
This is not the full code. but I think it will help to you

In MVC 3 I have a View with 3 Partial Views. How do i get the 3rd partial view to display on the same page?

I have a view with 3 partial views. The first partial view has a dropdown list. You select something from the dropdown then the 2nd partial view will load right under it on the same page.
Then I have a search form (html.BeginForm) in my second partial view and when I submit the form I want to open up the 3rd partial view under the 2nd one.
The 3rd partial view has a kendo ui grid that takes a model.
The problem right now is that the 3rd partial view is getting rendered on a different page.
View:
<section>
<div id="searchpanel">
#html.Partial("_1stPartial")
<div id="2ndPartialDiv"></div>
<div id="3rdPartialDiv"></div>
</div>
</section>
Partial View2:
<section>
<div id="searchblock">
<table>
<tr>
<td>
#using (Ajax.BeginForm("Search", "ControllerName", new AjaxOptions { updateTargetId = "3rdPartialDiv"}))
<fieldset>
<ol>
<li></li>
<li>
<input type="submit" value="Search" id="btnSearch"/>
</li>
</ol>
</fieldset>
</td>
</tr>
</table>
</div>
</section>
Controller:
public ActionResult Search(model)
{
//fill searchresults
return PartialView("_3rdPartial", searchresults);
}
Html.BeginForm will perform a full page post. I believe what you are after is Ajax.BeginForm.
http://msdn.microsoft.com/en-us/library/system.web.mvc.ajax.ajaxextensions.beginform(v=vs.118).aspx
Example:
#using (Ajax.BeginForm("TheActionResultYouWantToInvokeThatWillReturnTheThirdView", "YourController", null, new AjaxOptions { UpdateTargetId = "theIdOfTheDivForTheThirdView", OnSuccess = "doFunctionIfYouNeedTo", OnFailure = "ShowPopUpErrorIfYouWant" }))
{
}
Post code added edit:
This markup was invalid, and probably why UpdateTargetId is not finding the Div.
<section>
<div id="searchpanel">
#html.Partial("_1stPartial")
<div id="2ndPartialDiv"></div>
<div id="3rdPartialDiv"></div>
</div>
</section>
See closing speech marks on attributes.
What I understood from you question is that you're making a submit from the first PartialView and, if this was successfully, you'll show the 2nd one. Same for this one. If a successfully POST was made from the second PartialView, you want to show the 3rd one.
Why don't you do it with Ajax, from the client side?
$.ajax ({
type:'POST'
data: {},
success: function(response){
$('.specific_div_container_for_previous_partial').hide();
$('.specific_div_container_for_partial').html(response.Html);
$('.specific_div_container_for_partial').show();
},
error: function(){
// whatever
}
});
On the server side you'll return the rendered html with your PartialView. To render a PartialView in variable and send it the client side as a json object, please check out THIS
Update - How to serialize form in jquery :
Please follow THIS

Uploading file in with ASP.NET MVC3 (OpenFileDialog alternative)

I'm trying to replicate some webforms functionality that uploads a csv file in an MVC3 project and am coming unstuck. I have the following requirements:
(Short version is that I need something similar to the Filter, InitialDirectory and preferably but not necessarily, the MultiSelect properties of the System.Windows.Controls.OpenFileDialog class for MVC3)
Single button displayed that opens the open file dialog
Upload begins when open is clicked in the dialog
The file type in the dialog should be restricted to csv, txt and All files
The initial directory should be able to be set depending on user preferences
I've used jQuery for the first two requirements (shown below) but am not if this is the best way or how to accomplish the last two.
View:
#using (Html.BeginForm("Import", "Date", FormMethod.Post, new { enctype = "multipart/form-data", id="fileUpload" }))
{
<input type="file" name="file" id="file" style="display: none;" />
<input type="button" id="import" value="Import" />
}
<script type="text/javascript">
$(document).ready(function () {
$('#file').change(function () {
$('#fileUpload').submit();
});
$('#import').click(function () {
$('#file').trigger('click');
});
});
</script>
Controller:
[HttpPost]
public ActionResult Import(HttpPostedFileBase file)
{
// do stuff
}
Any ideas?
It's not possible to do unless you use a Flash or Silverlight plugin. I use Uploadify and it should do everything you need.

Categories

Resources