Failed to pass routeValues to an action from partial view - c#

I wanna add search functionality in my MVC application. This functionality should be available for all pages. So, I added it into the shared layout.
The only problem I have is that I'm not able to pass the routValues to the Search action in spite of I'm creating a new Form inside the partial view.
Target action:(performs the search)
[HttpPost]
public ActionResult Search(SearchModel keyword)
{
// keyword is always null
return RedirectToAction("SearchResult", keyword.keyword);
}
public class SearchModel { public string Keyword { get; set; } }
The Partial View:
#model DocuLine.Models.SearchModel
#using (Html.BeginForm("Search", "Home", FormMethod.Post))
{
#Html.EditorFor(model => model.Keyword)
<input type="submit" value="Search" />
}

Try
public ActionResult Search(SearchModel model)

Why the class is defined as Keyword and then view SearchResult you pass it as a keyword (lower case first letter)?
1 UpdateModel
You can update the class SearchModel with the method UpdateModel to check if you can make the correct assignment.
2 FormCollection
You can try to receive as parameter in the method Search form data (FormCollection) and check if you get what you require.

Finally, I solve it. The problem is that the SearchModel parameter name is keyword and it should be anything except keyword becuase there's already an html control is rendered with this name.
To solve it, it should only be named with another name:
public ActionResult Search(SearchModel model)
{
// model now has a value.
}

Related

Check Box Value Passed In FormCollection MVC Form

I have a FormCollection being passed back to a controller, which is processed, however, the value passed back if its true is 'true,false' but if it's unchecked it's just 'false'. My field uses iChecks.
My object that is being built is as follows:
field.IsSelected = Convert.ToBoolean(form["Field.IsChecked"]);
What would be the best method to get the correct value?
I would suggest doing :
form["Field.IsChecked"].Contains("true")
Which already returns a bool so you dont have to convert.
OR
You could go:
Convert.ToBoolean(form["Field.IsChecked"].Split(',').First());
or
Convert.ToBoolean(form["Field.IsChecked"].Split(',')[0]);
It would be better to use the Model Binder for this purpose, it is the right way for doing this nowadays, you can simply add a boolean property to your model class, and then use the checkbox helper of MVC.
public class YourViewModel
{
public bool IsChecked { get; set; }
}
And your ActionMethod:
public async Task<ActionResult> Index(YourViewModel viewModel)
{
field.IsSelected = viewModel.IsChecked;
}
And your view something like this:
#using (Html.BeginForm("Index", "YourController", FormMethod.Post))
{
<div>
#Html.CheckBox("IsChecked")
</div>
<input type="submit" value="Submit" />
}
This worked for me
Convert.ToBoolean(form["Field.IsChecked"].Split(',').First());

pass multiple values/parameters from view to mvc controller shorter way

Im new to MVC.. and started to grasp it. I am wondering whether there's a shorter way to pass parameters from view to mvc controller. I am creating a search box with possible conditions.
here's the sample code in the view
#using (Html.BeginForm("Action", "Controller", FormMethod.Get))
{
<p>
Find by fname: #Html.TextBox("fname", ViewBag.CurrentFilter as string)
<br/>
Find by lname: #Html.TextBox("lname", ViewBag.CurrentFilter as string)
<br/>
By Area Code : #Html.TextBox("AreaCode")
<br/>
#Html.DropDownList("StateCD", new SelectList(ViewBag.State))
<br/>
<input id="Button1" type="submit" value="Search"/>
</p>
}
in my controller
public async Task<ActionResult> Action(string id, string sortorder, string statecd,int? page,string country,string areacode,string city,string zip,string z)
{
}
is there a way to shorten that parameter like as an object or concatenated values?
You can create a class to represent your search filter and use that as the action method parameter type.
public class SearchVm
{
public strng StateCd { set;get;}
public string AreaCode { set;get;}
public string Zip { set;get;}
// Add other needed properties as well
}
and use that as the param
public async Task<ActionResult> Search(SearchVm model)
{
// check model.AreaCode value etc..
// to do : Return something
}
When the form is submitted Default Model binder will be able to map the posted form data to properties of the method parameter object, assuming your form field name's match with the class property names

ASPNET MVC 5 Html helper Action method view results input id missing (sometimes..) Possible Bug?

To recreate the issue I'm having I've set up two simple controller actions, two views and a view model:
MultiForms Action (in the form controller class)
public class FormController : Controller
{
[HttpGet]
public ActionResult MultiForms()
{
return View("MultiForms");
}
// ...
MultiForms.cshtml - Razor View
#Html.Action("MyFormGet", "Form")
Notice in the action method I call the controller method that returns the form partial view.
MyFormGet Action
[HttpGet]
public PartialViewResult MyFormGet()
{
var viewModel = new MyFormViewModel();
ViewData.TemplateInfo.HtmlFieldPrefix = Guid.NewGuid().ToString().Replace("-", "_");
return PartialView("MyForm", viewModel);
}
View Model
public class MyFormViewModel
{
public string TextInput1 { get; set; }
}
MyForm.cshtml - Razor View
#model Mvc5App.Controllers.MyFormViewModel
#using (Html.BeginForm("MyFormPost", "Form", FormMethod.Post))
{
<br />
#Html.TextBoxFor(m => m.TextInput1)
}
When I point my browser at /Form/MultiForms I get the output I expect:
<input type="text" value="" name="e166fa0d_46fe_40d4_a970_73c52a35f224.TextInput1" id="e166fa0d_46fe_40d4_a970_73c52a35f224_TextInput1">
Then I refresh the page and the output becomes this:
<input type="text" value="" name="48edc339_69ad_4b9b_9583_198038beab45.TextInput1">
Where did the id attribute go? Is this a bug in ASPNET MVC5 or have I done something wrong with this setup?
Thanks to #demo I think I figured out when the id doesn't show up...
If the id starts with a digit(or underscore) it will not render. So this GUID will render:
f3b1a447_3786_4472_9dfe_14c3ae8aae24
But this one will not:
1c26ce3d_5c71_408a_aae2_7be414f1d383
The solution for the above seems to be prefixing with something like this:
FOO_1c26ce3d_5c71_408a_aae2_7be414f1d383
And the problems go away.

Render Partial View only after HttpPost ActionHandler

I am making WCF service call using MyViewRequest view fields inside HttpPost ActionHandler. The goal is to show response using partial view, MyViewResponse
In brief I need to achieve these two items-
Disable load of partial view on first load.
Display Response (along with Request) after service call.
MyViewRequest.cshtml
#using (Html.BeginForm())
{
#Html.ValidationSummary(false)
//html code
}
</div>
<div id="dvResponse">
#Html.Partial("MyViewResponse");
</div>
Partial view: MyViewResponse.cshtml
#model MvcApplication3.Models.MyModel
#{
ViewBag.Title = "MyViewResponse";
}
<h2>MyView</h2>
#Html.Label(Model.MyName, "My Name")
This was pretty straight forward in Asp.Net using userControl, But stuck up here, How can we achieve this in MVC3.
I think the best way is to transfer your data using ViewModels. Let's assume you want to have an app something like stackoverflow where you have a question and user can post an answer and it will be shown after the post along with the question.
public class PostViewModel
{
public int ID { set;get;}
public string Text { set;get;}
public List<PostViewModel> Answers { set;get;}
public string NewAnswer { set;get;}
}
in your GET action, you show the question. Get the id from the url and get the Question details from your service/repositary.
public ActionResult Show(int id)
{
var post=new PostViewModel();
post=yourService.GetQuestionFromID(id);
post.Answers=yourService.GetAnswersFromQuestionID(id);
return View(post);
}
Assuming yourService.GetQuestionFromID method returns an object of PostViewModel with the propety values filled. The data can be fetched from your database or via a WCF service call. It is up to you. Also yourService.GetAnswersFromQuestionID method returns a list of PostViewModel to represent the Answers for that question. You may put both these into a single method called GetQuestionWithAnswers. I wrote 2 methods to make it more clear.
Now in your Show view
#model PostViewModel
#Html.LabelFor(x=>x.Text);
#using(Html.Beginform())
{
#Html.HiddenFor(x=>x.ID);
#Html.TextBoxFor(x=>x.NewAnswer)
<input type="submit" />
}
<h3>Answers</h3>
#if(Model.Answers!=null)
{
#Html.Partial("Responses",Model.Answers)
}
And your Partial view will be strongly typed to a collection of PostViewModel
#model List<PostViewModel>
#foreach(var item in Model)
{
<div> #item.Text </div>
}
Handling the postback is simple (HttpPost)
[HttpPost]
public ActionResult Show(PostViewModel model)
{
if(ModelState.IsValid)
{
//get your data from model.NewAnswer property and save to your data base
//or call WCF method to save it.
//After saving, Let's redirect to the GET action (PRG pattern)
return RedirectToAction("Show",new { #id=model.ID});
}
}

Performing search in Asp.net MVC

I am new to Asp.net MVC and have no idea as to how can i perform the search. Here's my requirement, please tell me how will you handle this :-
I need to have textbox where user can enter a search query or string. The user then clicks on a button or presses enter to submit it. The string needs to matched with a table's property name.
NOTE:- Querying the data and fetching the result isn't the main point here. All I need to know is how will you take the user input and pass it to a controller action or whatever for further processing. Just tell me how will you read the user input and where will you send it to search.
Asp.Net MVC uses standard HTTP verbs. For the html part, it's a normal html form that points to an url. Server side, that url will be routed to a controller/action which will handle the input and do what is needed.
Let's have a sample. You want to make a search form. First of all, it's a best practice to have search forms use the HTTP GET method instead of POST, so the search results can be bookmarked, linked, indexed, etc. I won't be using Html.BeginForm helper method to make things more clear.
<form method="get" action="#Url.Action("MyAction", "MyController")">
<label for="search">Search</label>
<input type="text" name="search" id="search" />
<button type="submit">Perform search</button>
</form>
That's all the html you need. Now you'll have a controller called "MyController" and the method will be something like this:
[HttpGet]
public ActionResult MyAction(string search)
{
//do whatever you need with the parameter,
//like using it as parameter in Linq to Entities or Linq to Sql, etc.
//Suppose your search result will be put in variable "result".
ViewData.Model = result;
return View();
}
Now the view called "MyAction" will be rendered, and the Model of that view will be your "result". Then you'll display it as you wish.
As always in an ASP.NET MVC application you start by defining a view model which will express the structure and requirements of your view. So far you have talked about a form containing a search input:
public class SearchViewModel
{
[DisplayName("search query *")]
[Required]
public string Query { get; set; }
}
then you write a controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new SearchViewModel());
}
[HttpPost]
public ActionResult Index(SearchViewModel model)
{
if (!ModelState.IsValid)
{
// There was a validation error => redisplay the view so
// that the user can fix it
return View(model);
}
// At this stage we know that the model is valid. The model.Query
// property will contain whatever value the user entered in the input
// So here you could search your datastore and return the results
// You haven't explained under what form you need the results so
// depending on that you could add other property to the view model
// which will store those results and populate it here
return View(model);
}
}
and finally a view:
#model SearchViewModel
#using (Html.BeginForm())
{
#Html.LabelFor(x => x.Query)
#Html.EditorFor(x => x.Query)
#Html.ValidationMessageFor(x => x.Query)
<button type="submit">Search</button>
}
This is the best way to do it.
Create a ViewModel
public class SearchViewModel
{
public string Query { get; set; }
}
Create a Controller
public class SearchController : Controller
{
[HttpPost]
public ActionResult Search(SearchViewModel model)
{
// perform search based on model.Query
// return a View with your Data.
}
}
Create the View
// in your view
#using (Html.BeginForm("Search", "SearchController"))
{
#Html.TextBox("Query")
<input type="submit" value="search" />
}
hope this helps

Categories