Get Query Parameter from URL into MVC View - c#

I have an a href link to a page which adds a parameter to the link for example:
tsw/register-your-interest?Course=979
What I am trying to do is to extract the value in Course i.e 979 and display it in the view. When attempting with the below code, I only return with 0 rather than the course value expected. ideally I'd like to avoid using routes.
Here is the view:
<div class="contact" data-component="components/checkout">
#using (Html.BeginUmbracoForm<CourseEnquiryPageSurfaceController>("PostCourseEnquiryForm", FormMethod.Post, new { id = "checkout__form" }))
{
//#Html.ValidationSummary(false)
#Model.Course;
}
And my controller:
public ActionResult CourseEnquiry(string Course)
{
var model = Mapper.Map<CourseEnquiryVM>(CurrentContent);
model.Course = Request.QueryString["Course"];
return model
}
This is the View Model:
public class CourseEnquiryVM : PageContentVM
{
public List<OfficeLocation> OfficeLocations { get; set; }
public string Test { get; set; }
public string Course { get; set; }
public List<Source> SourceTypes { get; set; }
}
SOLUTION:
After some research and comments I've adjusted the code to the below which now retrieves the value as expected
#Html.HiddenFor(m => m.Course, new { Value = #HttpContext.Current.Request.QueryString["Course"]});
Thanks all

Based on the form code you provided you need to use #Html.HiddenFor(m => m.Course) instead of just #Model.Course. #Model.Course just displays the value as text instead of building a input element that will be sent back to your controller.
If your problem is with a link prior to the view you referenced above, here's what I'd expect to work:
View with link:
#model CourseEnquiryVM
#Html.ActionLink("MyLink","CourseEnquiry","CourseController", new {course = #Model.Course}, null)
CourseController:
public ActionResult CourseEnquiry(string course)
{
// course should have a value at this point
}

In your view, you are only displaying the value of Course.. which isn't able to be submitted. You need to incorporate the value of course with a form input element (textbox, checkbox, textarea, hidden, etc.).
I would highly suggest using EditorFor or Textboxfor, but because your controller action is expecting just a string parameter you could just use Editor or TextBox.
#using (Html.BeginUmbracoForm<CourseEnquiryPageSurfaceController>("PostCourseEnquiryForm", FormMethod.Post, new { id = "checkout__form" }))
{
//#Html.ValidationSummary(false)
#Html.TextBox(Model.Course, null, new { #class = "form-control"});
<input type="submit" value="Submit" />
}
Then you should just be able to do this in your controller:
public ActionResult CourseEnquiry(string course) // parameter variables are camel-case
{
var model = Mapper.Map<CourseEnquiryVM>(CurrentContent);
if(!string.IsNullOrWhiteSpace(course))
model.Course = course;
return model;
}
Let me know if this helps.

Related

Remember search params

I'm new in mvc and I try to create a simple page with table and ajax search.
For example, I have a search model, which pass parameters from form to controller.
Model:
public class OrderSearchViewModel
{
[Display(ResourceType = typeof(Lang), Name = "OrderID")]
public int? OrderID { get; set; }
[Display(ResourceType = typeof(Lang), Name = "DeliveryType")]
public int? DeliveryTypeID { get; set; }
[Display(ResourceType = typeof(Lang), Name = "Partner")]
public string CustomerName { get; set; }
public SelectList DeliveryTypes { get; set; }
}
In controller I have an action witch return View with form:
public ActionResult Index()
{
var ordersSearchModel = // default init;
return View(model);
}
In my Index.cshtml I have a form
#model Models.Order.OrderSearchViewModel
<div class="row">
#using (Ajax.BeginForm("Orders", "Order", new AjaxOptions {UpdateTargetId = "ordersList"}, new {#id = "searchForm", #class = "form-horizontal"}))
{
// Editors templates for each params
}
</div>
<div id="ordersList" class="row">
</div>
}
In my Controller I have a method, witch take search model and return a partial view
[HttpPost]
public async Task<ActionResult> Orders(OrderSearchViewModel model, int page = 1, int pageSize = 50)
{
var models = // connect to db and get data filtered by model params
return PartilaView("_View", models);
}
In result partial I have a table with order num and link to edit view.
In edit view I have a link back to search:
#Html.ActionLink("Back", "Index", "Order", new { #class = "btn btn-default" })
And by click this link I get the Index view in default (without search parameters) and user must fill it once again.
What will be the best practice to remember user search parameters?
Thanks for any advice.
As devqon said, the preferred approach is to use query parameters, but it does sound like your usage might make this a bit difficult to manage
TempData/SessionData may solve your issue, but using this approach will cause problems if the user decides to use your application in multiple tabs/windows (they will all share the same search params)
Something that might be worth looking into is SessionStorage.(Link below)
This type of storage persists as long as the browser stays open
And importantly
Opening a page in a new tab or window will cause a new session to be initiated
So your pages shouldn't share state.
More details here:
https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage

Using .net MVC why don't my lists survive a post?

I'm just picking up .net MVC and I've come across something that I can't work out. I'm obviously missing some basic principle but would love some help.
I have a ViewModel with two IEnumerables that I want to use to create dropdownlistfors. My GET works fine, the lists are populated as expected.
Now I'm posting the ViewModel back to a POST method, not to do anything useful but just to try and understand how mvc works. I expected that I would simply be able to re-populate the dropdownlistfors from the model that was posted back - but I get a null reference exception.
Other values, such as partyid, in the ViewModel survive the POST so i'm confused.
I can get it to work if I repopulate the lists but that seems wrong.
Can someone give me a pointer?
My ViewModel
public class DemoViewModel
{
//properties
public IEnumerable<tbl_server_lookup> servers { get; set; }
public int serverId { get; set; }
public IEnumerable<tbl_site_lookup> sites { get; set; }
public int siteId { get; set; }
public int partyid { get; set; }
public string message { get; set; }
public DemoViewModel()
{
}
}
My Controller
// GET: /Demos/Test/
[HttpGet]
public ActionResult Test()
{
DemoViewModel demo = new DemoViewModel();
using (var dbContext = new ADAPI.Models.db_ad_apiEntities2())
{
var serverList = dbContext.tbl_server_lookup.Where(s => s.server_name != null);
demo.servers = serverList.ToList();
var siteList = dbContext.tbl_site_lookup.Where(w => w.site_name != null);
demo.sites = siteList.ToList();
}
demo.message = "Enter the user id you would like to look up in the box below.";
return View(demo);
}
//
//POST: /Demos/Test/
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Test(DemoViewModel demo)
{
//It works if I uncomment this block...
/*using (var dbContext = new ADAPI.Models.db_ad_apiEntities2())
{
var myQuery = dbContext.tbl_server_lookup.Where(s => s.server_name != null);
demo.servers = myQuery.ToList();
var siteList = dbContext.tbl_site_lookup.Where(w => w.site_name != null);
demo.sites = siteList.ToList();
}*/
demo.message = "the user id you posted is: " + demo.partyid + ". The Server you selected is: ";// +demo.serverId;
return View(demo);
}
My View
#model ADAPI.ViewModels.DemoViewModel
<h2>Demos</h2>
<h3>#Model.message</h3>
#using (Html.BeginForm("Test","Demos"))
{
#Html.AntiForgeryToken()
<div class="">
<h4>Party ID</h4>
#Html.ValidationSummary(true)
<!-- input box for party id-->
#Html.TextBoxFor(model => model.partyid)
<!-- dropdown list of server types eg live vs test-->
#Html.DropDownListFor(model => model.serverId, new SelectList(Model.servers, "server_Id","server_name"))
#Html.DropDownListFor(model => model.siteId, new SelectList(Model.sites, "site_short_name","site_name"))
<input type="submit" value="Try" />
</div>
}
The Error
In MVC, model on the views are loaded in the controller action, they are not posted back along with the post action.
If you are used to ASPX's viewstate, there is no such thing in MVC, you need to load what you need for every view in the current action.
Dropdown lists are rendered into html as tag and returned to the server as plain single value.
You have to rebind/repopulate them on the server, wchich is annoying in scenarios like validation, where the same model should be returned to the client.
There is no support for that in the framework - you have to do it on your own.
One more thing - if you absolutely have to return the list items and want them back on the server, you can serialize tham and hide in some hidden field. But it's ugly and unsecure since anyone can change its value.

model returned to view has no effect on field

My Model;
namespace GeneralUtility.Models
{
public class MyModel
{
public int BirthDateYear { get; set; }
public String Details { get; set; }
}
}
My Controller
namespace GeneralUtility.Controllers
{
public class WorkspaceController : Controller
{
public ActionResult MyHelper(MyModel model)
{
if(model.someCondition)
model.Details= "TEST";
else
model.Details= "Some other TEST";
return View(model);
}
}
}
My View
<div data-role="fieldcontain">
#using (Html.BeginForm("MyHelper", "WorkSpace", FormMethod.Post, new { id = "frmMyForm" }))
{
...
<div data-role="fieldcontain">
#Html.EditorFor(x => x.Details )
</div>
...
}
</div>
After I submit my form, I can see the model and any changes I make in MyHelper action method. However, when I make changes and return the model from the controller (I can see the changes in the model while in debug). I get the same value as before in #Html.EditorFor(x => x.Details ) field. What can I do to get the changed Details value of the model to show?
That's because by default ASP.NET MVC returns the model that was passed into a method (using what is stored in the ModelState, if it exists). If it doesn't exist, it uses what you pass to the View.
In order to prevent this, you need to call ModelState.Clear() before returning your view.
Check this blog post for a more detailed explanation.

How to add values to dropdown in MVC3?

I want to add a dropdownlist in my form, with 2 values userid and username in my dropdownlist, and also I want to get the value selected by the user when I click the button. I'm new to MVC and so far, I have not worked on dropdownlist, tried few samples but nothing seems to be working the way I want.
I'll jump lots of MVC3 concepts. If you're really new to ASP.NET MVC, you should take a look at some tutorials.
This code should help you:
VIEW
#using (Html.BeginForm("ACTION NAME", "CONTROLLER NAME"))
{
<select name="select">
<option value="username" selected>User name</option>
<option value="userid">User id</option>
</select>
<input type="submit" />
}
ACTION
[HttpPost]
public ActionResult ACTIONNAME(string select)
{
//...
}
Please, note:
ACTION NAME and CONTROLLER NAME at the BeginForm helper. You will have to modify this at your code
The select name ("select") and the name of the argument at the action ("select"). This is not a coincidence, it's a convention. MVC uses the name attr to bind data
The selected attribute at the option will make it the default option
Regards
See one of the ways you can do it is send the list in a model property as the binding and for the value you can bind it to another property like :
public class YourModel
{
public List<UserList> OptionList { get; set; }
public String YourValue{get;set;}
}
public class UserList
{
public String UserName{get;set;}
public String UserId{get;set;}
}
#Html.DropDownListFor(model => model.YourValue, Model.OptionList, "")
In the helper there are overided options which are used to specify the value and text.
And Remember :
This is StackOverflow.
Even the Not working example which you have tried are important for the ones who try to help you since they are spending their precious bandwidths for u.
You don't need create a new model class for each view, just put this on controller:
ViewBag.FieldName = new SelectList(new List<SelectListItem>() {
new SelectListItem { Value = "userid", Text = "User ID" },
new SelectListItem { Value = "username", Text = "User name" }
});
And this on view:
#Html.DropDownList("FieldName")
You need to create a collection of SelectListItem like:
IEnumerable<SelectListItem> selectList =
from c in areaListResponse.Item
select new SelectListItem
{
Text = c.AreaName,
Value = c.Id.ToString()
};
Pass this selectList to your view:
return View(selectList);
In your cshtml:
#model IEnumerable<SelectListItem>
#Html.DropDownListFor(m => m.RequestAreaName, Model)
If you need complecated object, you may need a wrapper class like:
public class RaiseRequestModelWrapper
{
public IEnumerable<SelectListItem> GetModel { get; set; }
public RaiseRequestModel PostModel { get; set; }
}

Model binding for a ViewModel containing multiple objects

I have a strongly typed view of type ProductListingViewModel which in turn contains a ProductViewModel. (both custom view models).
I have some form elements on my page and these are created like so:
<%: Html.DropDownListFor(m => m.ProductViewModel.CategoryId, Model.Categories)%>
which generates the HTML:
<select name="ProductViewModel.CategoryId" id="CategoryId">
With the default model binding I expected that when I post to my controller action which accepts a parameter of type ProductListingViewModel, that it'd know to populate the ProductViewModel.CategoryId with the relevant data.
The name of the select list seems to indicate that it knows there's a ProductViewModel with a CategoryId property however when I post to my controller method, the ProductViewModel is null. If I create this during construction of the ProductListingViewModel then it's no longer null but the default binder doesn't seem to be populating the properties as I expected.
Is this a case for a custom model binder or am I just missing something fundamental?
Cheers.
Let me try to summarize (correct me if I am wrong).
Model:
public class ProductListingViewModel
{
public ProductViewModel ProductViewModel { get; set; }
public IEnumerable<SelectListItem> Categories { get; set; }
}
public class ProductViewModel
{
public string CategoryId { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new ProductListingViewModel
{
Categories = new SelectList(new[]
{
new { Value = "1", Text = "category 1" },
new { Value = "2", Text = "category 2" }
}, "Value", "Text")
};
return View(model);
}
[HttpPost]
public ActionResult Index(ProductListingViewModel model)
{
return View(model);
}
}
View:
<% using (Html.BeginForm()) { %>
<%: Html.DropDownListFor(m => m.ProductViewModel.CategoryId, Model.Categories)%>
<input type="submit" value="OK" />
<% } %>
Now when you submit the form you will get:
model.ProductViewModel.CategoryId = the id that was selected in the drop down list
Isn't what you are after?
It seems to me that the default binder should work in this case.
Did you try using Fiddler for checking the data sent from the client?
What exactly is the signature of the controller action?

Categories

Resources