MVC parial view going to get method rather than post on submit - asp.net-mvc

I have a partial view which shows a search box with a couple of options
model PatientSearchViewModel
#using (Html.BeginForm("Index", "Patient", FormMethod.Post, new { #class = "form-inline" }))
{
<form class="form-inline">
<label style="padding-right:20px;">Search for a patient</label>
#Html.EditorFor(model => model.SearchText, new { htmlAttributes = new { #class = "form-control", placeholder = "Search...", autocomplete = "off" } })
<div class="checkbox">
<div class="checkbox" style="padding-left:20px; padding-right:20px;">
<label>#Html.EditorFor(model => model.ShowOnlyOpenClients) Show only open clients</label>
</div>
</div>
<button type='submit' name='seach' id='search-btn' class="btn btn-primary"><i class="fa fa-search"></i>Search</button>
</form>
}
When the submit button is hit I want it to go to my method below with the search content already complete, however instead it goes to the HttpGet method which is bringing back a null for the PatientSearchViewModel.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(PatientSearchViewModel patient)
{
PatientSearchViewModel patientVM = GetSearchResults(patient);
return View(patientVM);
}
Can anyone explain how I can get this to work?

I have executed the code snippet you pasted here and found that
As you are making the use of the [ValidateAntiForgeryToken]
attribute so you need to add the #Html.AntiForgeryToken(); this
statement in your partial view inside the
#using(Html.BeginForm()){ } block.
One more thing make sure that your action method will be inside the
PatientController.
For your reference (this is my code)
#model WebApplication.Models.PatientSearchViewModel
#using (Html.BeginForm("Index", "Patient", FormMethod.Post, new { #class = "form-inline" }))
{
#Html.AntiForgeryToken();
<label style="padding-right:20px;">Search for a patient</label>
#Html.EditorFor(model => model.SearchText, new { htmlAttributes = new { #class = "form-control", placeholder = "Search...", autocomplete = "off" } })
<div class="checkbox">
<div class="checkbox" style="padding-left:20px; padding-right:20px;">
<label>#Html.EditorFor(model => model.ShowOnlyOpenClients) Show only open clients</label>
</div>
</div>
<button type='submit' name='seach' id='search-btn' class="btn btn-primary"><i class="fa fa-search"></i>Search</button>
}
Suggestion: As you have used the #using(Html.BeginForm()) which will any way going to convert to <form> tag so instead of using another <form class="form-inline"> inside it is creating the confusion please you may remove it.
I hope this will solve your problem.

Related

How to validate a duplicate post request from a form in MVC

I am having an form which insert a record whenever a post request is made,but the problem is that if someone clicks submit button more than 1 times than duplicate post request are made and at the end same records are getting inserted. I dont want to check that the record is already present or not because the record would be different always. I tried using ValidateAntiForgeryToken filter in controller but it is failing to validate the requests, Below is my View Code.
#using (Html.BeginForm("Create", "Home",FormMethod.Post,new { onkeydown = "return event.keyCode!=13" }))
{
#Html.AntiForgeryToken()
<div class="right-col">
#Html.TextBoxFor(model => model.Name, new { placeholder = "Name", #class = "small-box" })
</div>
<div class="left-col">Email Id :</div>
<div class="right-col">
#Html.TextBoxFor(model => model.EmailId, new { placeholder = "Email Id", #class = "small-box",id="resumeemailid" })
#Html.ValidationMessageFor(model => model.EmailId)
</div>
<div class="left-col">Address :</div>
<div class="right-col">
#Html.TextAreaFor(model => model.Address, new { placeholder = "Address", #class = "small-box" })
</div>
<div class="buttons resume-threebutton">
<input type="submit" id="register-button" class="gradient-btn" value="#T("Account.Passport.Register.Button.Upload", "Upload")" name="Command" />
<input type="submit" id="register-button" class="gradient-btn" value="#T("Account.Passport.Button.UploadandAdd", "Upload And Add New")" name="Command" />
<input type="button" id="register-button" class="gradient-btn" value="#T("Account.Passport.Register.Button.Cancel", "cancel")" name="register-button" onclick="location.href='#Url.Action("SelectTemplate", "CustomerTemplate")'" />
</div>
}
and below is my controller Post method
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ProductModel model)
{
//To do add the product here...
}

Partial view doesn't load inside current view

So I have this partial view:
#model QueryQuestionManager.Models.Domain.Answer
<script src="~/Scripts/DynamicList.js"></script>
<div class="editorRow">
#using (Html.BeginCollectionItem("Answers"))
{
<div>
#Html.LabelFor(x => x.AnswerText)
#Html.EditorFor(x => x.AnswerText)
</div>
delete
}
</div>
I want to load this partial view in my main view when someone clicks the link:
#model QueryQuestionManager.Models.Domain.Question
#{
ViewBag.Title = "Create";
}
<script src="~/Scripts/DynamicList.js"></script>
<br />
#using (Html.BeginForm(new { #class = "form", role = "form" }))
{
<div class="form-group">
<div class="editor-label">
#Html.LabelFor(m => m.QuestionText)
</div>
<div class="form-control">
#Html.TextBoxFor(m => m.QuestionText)
#Html.ValidationMessageFor(m => m.QuestionText)
</div>
<div class="editor-label">
#Html.LabelFor(m => m.Category)
</div>
<div class="form-control">
#Html.TextBoxFor(m => m.Category)
#Html.ValidationMessageFor(m => m.Category)
</div>
<div class="editor-label">
#Html.LabelFor(m => m.Answers)
</div>
<br />
<div id="editorRows">
#foreach (var item in Model.Answers)
{
#Html.Partial("EditorRow", item);
}
</div>
#Html.ActionLink("Add another...", "BlankEditorRow", "Question", new { id = "addItem" })
<br />
<input type="submit" value="Save" class="btn btn-success" />
</div>
}
<br />
<div>
#Html.ActionLink("Back to List", "Index", "Home")
</div>
This is the action result from the controller
public ActionResult BlankEditorRow()
{
return PartialView("EditorRow", new Answer());
}
And then I have a javascript file for the dynamic adding and deleting partial views.
$('#addItem').click(function () {
$.ajax({
url: this.href,
cache: false,
success: function (html) {
$('#editorRows').append(html);
}
});
return false;
});
$('a.deleteRow').live('click', function () {
$(this).parents('div.editorRow:first').remove();
return false;
});
But for some reason my partial view doesn't load inside my current view and it opens only the partial view.
Am I forgetting something?
I'm thinking you don't want that action link. I believe your jQuery click handler has the correct approach, but your action link is linking to your new URL (Question/BlankEditorRow) and you don't want that. Rather you just need to fetch this html, and insert it as you do, but WITHOUT navigating the main page to that URL.
Instead of the ActionLink, use an anchor tag and a hidden field.
<a id="addItem" href="#" />
<input type="hidden" id="partialViewAction" value="#Url.Action("BlankEditorRow","ControllerName")"
Now in your ajax call, instead of using the href property of the anchor, use the value of the hidden field.
url: $('#partialViewAction').val()

ActionResult not being called when using [AcceptVerbs(HttpVerbs.Post)]

The ActionResult in the controller is not being called. The page is just refreshing.
Check my code below:
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<fieldset>
#if (#ViewBag.Message != null)
{
<p style="color: #b94a48;">#ViewBag.Message</p>
}
#Html.HiddenFor(model => model.Id)
<div class="form-group">
<label class="control-label visible-ie8 visible-ie9">Username</label>
<div class="input-icon">
<i class="fa fa-user"></i>
#Html.TextBoxFor(model => model.UserName, new { #placeholder = "Email", #class = "form-control placeholder-no-fix" })
<p style="color: #b94a48;">#Html.ValidationMessageFor(model => model.UserName)</p>
</div>
</div>
<div class="form-group">
<label class="control-label visible-ie8 visible-ie9">Password</label>
<div class="input-icon">
<i class="fa fa-lock"></i>
#Html.PasswordFor(model => model.Password, new { #placeholder = "Password", #class = "form-control placeholder-no-fix" })
<p style="color: #b94a48;">#Html.ValidationMessageFor(model => model.Password)</p>
</div>
</div>
<div class="form-actions">
<div>
<label class="checkbox">
#Html.CheckBoxFor(model => model.RememberMe, new { #class = "remember" }) Remember me
</label>
</div>
<button type="submit" class="btn blue pull-right">
Login <i class="m-icon-swapright m-icon-white"></i>
</button>
</div>
</fieldset>
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Login(AccountViewModel model, FormCollection args, string ReturnUrl)
{
}
RouteConfig:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute("SJSS", "{controller}/Show/{assetCode}/{action}/{id}", new { controller = "Asset", action = "Index", id = UrlParameter.Optional });
routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Account", action = "Home", id = UrlParameter.Optional });
Try altering your #Html.BeginForm to this:
#Html.BeginForm("***Action Name***", "***Controller Name***", FormMethod.Post)
{
}
You need to specify an "Action", "Controller" and "Form method" for your form. See a code below:
#using (Html.BeginForm("Login", "Account", FormMethod.Post))
{
}
I might be mistaken here but despite the fact that your identation is a bit confusing, I can't find the url which you're posting to, I mean, your form action is empty, even if you submit, how would mvc know which action to call?
Try setting the action and controller parameters on Html.BeginForm.
edit: Check #Roman Denysenko's answer to see an example that might suit your case perfectly.

Using Html.Begin form and FormMethod.Get resulting in form posting

Using a Razor cshtml file in an MVC/Orchard application.
Form area reads as:
#using (Html.BeginForm("Action", "Controller", FormMethod.Get, new { area = "Area.area"})) {
Html.AntiForgeryToken();
#Html.LabelFor(model => model.Value)
#Html.EditorFor(model => model.Value)
<div class="actions">
#Html.ActionLink("Do Something", "OtherAction", "Controller", new { area = "Area.area"}, new { #class = "button"})
<button type="submit">Submit</button>
}
This results in the following HTML:
<form action="/Location/URL" method="post">
<!---Editor Fields etc-->
<div class="actions">
<a class="button" href="/Location/OtherURL">OtherAction</a>
<button type="submit">Submit</button>
</div>
</form>
As you can see, this form is assigned the POSTmethod, which as far as I can tell is contrary to the use of FormMethod.Get in the FormMethod argument of Html.BeginForm.
One things I did notice whilst testing out another form (the real form is much, much longer so I inserted a very small one to see if the syntax/behaviour checked out) was the following:
#using (Html.BeginForm("Action", "Controller", FormMethod.Get, new {area = "Area.area"})) {
<button value="submit">Test</button>
}
#using (Html.BeginForm("Action", "Controller", FormMethod.Get, new { area = "Area.area"})) {
Html.AntiForgeryToken();
#Html.LabelFor(model => model.Value)
#Html.EditorFor(model => model.Value)
<div class="actions">
#Html.ActionLink("Do Something", "OtherAction", "Controller", new { area = "Area.area"}, new { #class = "button"})
<button type="submit">Submit</button>
}
This resulted in the following:
<form action="/Location/URL" method="post">
<button value="submit">Test</button>
<form action="/Location/URL" area="Area.area" method="get">
<!---Editor Fields etc-->
<div class="actions">
<a class="button" href="/Location/OtherURL">OtherAction</a>
<button type="submit">Submit</button>
</div>
</form>
</form>
So this appears to have made the first form a POST and the second one a GET but has put the second form inside of the first one.
Can anyone shed any light?

Can not upload file/image

I am working on a simple form where user will enter some data and select a file to upload.
But i can not get this working..
For some reason when I click save, the file does not go to the controller.
Here is some code.
#using (Ajax.BeginForm("Add", "Category", null, new AjaxOptions
{
UpdateTargetId = "upload-message",
InsertionMode = InsertionMode.Replace,
HttpMethod = "POST",
OnSuccess = "uploadSuccess"
}, new { id = "AddCategoryForm", enctype = "multipart/form-data" }))
{
<div class="editorLabel">
#Html.LabelFor(m=>m.CategoryName)
</div>
<div class="editorText">
#Html.TextBoxFor(m=>m.CategoryName)
</div>
<div class="editorLabel">
#Html.LabelFor(m => m.Description)
</div>
<div class="editorText">
#Html.TextAreaFor(m => m.Description)
</div>
<div class="editorLabel">
#Html.LabelFor(m => m.IconPath)
</div>
<div class="editorText">
<input type="file" id="file" name="file" />
</div>
<div class="editorLabel">
#Html.LabelFor(m => m.IsActive)
</div>
<div class="editorText">
#Html.CheckBoxFor(m=>m.IsActive)
</div>
<p>
<input type="submit" id="submit" value="Save" />
</p>
}
Controller:
[HttpPost]
public ActionResult Add(HttpPostedFileBase file,CategoryViewModel model)
{
if (ModelState.IsValid)
{
System.IO.FileInfo info = new FileInfo(file.FileName);
string ext = info.Extension;
//other code
}
}
Here in the controller, file is always null.
Where am I doing wrong??
First swapping parameters of your controller to have it as follows:
[HttpPost]
public ActionResult Add(CategoryViewModel model, HttpPostedFileBase file)
For example.
If this won't work for some reason, make the file you uploading part of your model (CategoryViewModel) and have controller signature as follows:
[HttpPost]
public ActionResult Add(CategoryViewModel model)
For example. That way file will be returned as part of the model and you will extract it as one of model's properties. This will work (it worked for me).
Hope this helps.

Resources