Hide the parameters in query string using GridMvc and ActionLink MVC C# - c#

I am wondering if anyone could help me, the problem I have is that I am trying to not show the parameter in URL, when the parameter is posted to another controller. I have tried routing and changing the ActionLink. If anyone one could help it would be greatly appreciated.
I get "/Accounts/ViewCustomer/Index/3316", I want to hide 3316
Customer list view
#Html.Grid(Model.CustomerList).Columns(columns =>
{
columns.Add(data => data.Referance).Titled("Reference").Sanitized(false).Encoded(false).Filterable(true).
RenderValueAs(model => Html.ActionLink(model.Referance, "Index", "ViewCustomer",
routeValues: new { id = model.CustomerID },
htmlAttributes: new { id = "cust" }).ToHtmlString());
columns.Add(data => data.Company).Titled("Company").Sanitized(false).Encoded(false).Filterable(true).
RenderValueAs(model => Html.ActionLink(model.Company, "Index", "ViewCustomer", new { id = model.CustomerID }, null).ToHtmlString());
}).WithPaging(#ViewBag.Pagesize, #ViewBag.PageCountLimit).Sortable()
From view customer Controller to which int is posted
public ActionResult Index(int? id)
{
Paging paginginfo = GridPageProvider.Pagesize();
ViewData["Pagesize"] = paginginfo.Pagesize;
ViewData["PageCountLimit"] = paginginfo.PageCountLimit;
SetCustomerInfo(id);
if (_customerdetail.Contacts.Count != 0)
{
return View( _customerdetail);
}
else
{
return RedirectToAction("Index", "Home");
}
}

In this case 3316 is part of your URL and you can't hide it. But you can send id as parameter (you will need change routing) and use POST method to hide it in method body

Related

ASP POST ActionResult recieves a 0 instead of a provided ID value

Well, hello everyone.
I have a short ASP .NET MVC5 question. I have to pass a value from a ViewBag in the View method with a POST action result.
Create Method View Trigger
#Html.ActionLink("Add TestCase", "Create", "TestPlanTestCases", new { id = Model.TestPlan.ID }, null)
Controller Create GET method
public ActionResult Create(int id)
{
var testPlanFind = _db.TestPlan.Find(id);
ViewBag.TestPlanID = testPlanFind;
ViewBag.TestCaseID = new SelectList(_db.TestCase,"ID", "Name")
return View();
}
Create View, related DIV:
<div class="form-group">
#Html.LabelFor(model => model.TestPlanID, "TestPlanID", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.ViewBag.TestPlanID.Name
#Html.ValidationMessageFor(model => model.TestPlanID, "", new { #class = "text-danger" })
</div>
Controller Create POST method
public ActionResult Create([Bind(Include = "TestPlanID,TestCaseID")] TestPlanTestCases testPlanTestCases)
{
if (ModelState.IsValid)
{
_db.TestPlanTestCases.Add(testPlanTestCases);
_db.SaveChanges();
return RedirectToAction("Details", "TestPlans", new {id = testPlanTestCases.TestPlanID});
}
ViewBag.TestCaseID = new SelectList(_db.TestCase, "ID", "Name", testPlanTestCases.TestCaseID);
ViewBag.TestPlanID = new SelectList(_db.TestPlan, "ID", "Name", testPlanTestCases.TestPlanID);
return View(testPlanTestCases);
So, my problem is, when the POST method is being called, the method always receives TestPlanID = 0 and TestCaseID = (ID of the chosen test case). I've used the same workaround for a different controller that has similar functionality and it works perfectly fine, but for some reason, when it comes to setting a predefined value such as TestPlanID it is automatically being set to 0, not even a null. The GET method works fine and passes the right ID, but when it comes down to the POST method, something goes wrong.
I hope I have provided enough information for you to understand the issue.
Thanks in advance!
Well. I've finally solved it, maybe not the best solution, but it works.
A dev friend of mine suggested parsing the URL to get the ID in the POST method. So I've decided to add 3 additional lines of code to the controller, first one to parse the URL for ID value, second to convert the string to Int32, and then assign the result value to the testPlanTestCases.TestPlan.
Updated Controller:
public ActionResult Create([Bind(Include = "TestCaseID")] TestPlanTestCases testPlanTestCases)
{
var testPlanId = RouteData.Values["id"];
testPlanId = Convert.ToInt32(testPlanId);
testPlanTestCases.TestPlanID = (int) testPlanId;
if (ModelState.IsValid)
{
_db.TestPlanTestCases.Add(testPlanTestCases);
_db.SaveChanges();
return RedirectToAction("Details", "TestPlans", new {id = testPlanTestCases.TestPlanID});
}
ViewBag.TestCaseID = new SelectList(_db.TestCase, "ID", "Name", testPlanTestCases.TestCaseID);
ViewBag.TestPlanID = new SelectList(_db.TestPlan, "ID", "Name", testPlanTestCases.TestPlanID);
return View(testPlanTestCases);

Save querystring Bewteen Actions

I have an index action that can be filtered and is done so by using a query string. When I choose a record I move to the Details action. From there I can navigate to other actions related to this record which will then lead me back to the Details action. I would like to be able to save the URL from the Index page which will have the query string parameters intact. Obviously I can't do this with a straight Request.UrlReferrer since it won't be correct if the previous action wasn't Index. I have come up with a solution but I was wondering if there was a better way. Thanks!
public ActionResult Details(int? id)
{
var url = Request.UrlReferrer;
// Save URL if coming from the Employees/Index page
if (url != null && url.AbsolutePath == "/Employees")
Session.Add("OfficeURL", url.ToString());
// Model Stuff
return View();
}
Details View
#Html.ActionLink("Back to List", "Index", null, new { #href = Session["OfficeURL"] })
You need to pass a "return URL" with your links to the other views. Essentially:
Index.cshtml
#Html.ActionLink("View Details", "Details", "Foo", new { returnUrl = Request.RawUrl })
This will have the effect of putting the current index URL in the query string of the link. Then, in your other actions, you'll accept this as a param and store it in ViewBag:
public ActionResult Details(int? id, string returnUrl = null)
{
...
ViewBag.ReturnUrl = returnUrl;
return View();
}
Then, in these other views, you'll utilize this ViewBag member in the same way as above:
Details.cshtml
#Html.ActionLink("Click Me!", "Foo", "Foo", new { returnUrl = ViewBag.ReturnUrl })
When you're ready to go back to the index, then, you'd link/redirect to this return URL that you've been passing around.

MVC4 and Routing

I have a single controller and view working that calls a web service, and returns a result. At the moment, it's my default controller, called Home, and it uses the Index view page.
It's working. I can post data and then put something on the refreshed screen. It reloads the same view.
Now, once I submit, and I get a good reply, I want to load a different controller/view.
My routes look like this right now:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Home",
"{lang}",
new { controller = "Home", action = "Index", lang="English" });
routes.MapRoute(
"Location",
"{lang}",
new { controller = "Location", action = "Index", lang = "English" });
I created a controlled called Location, and it just has this:
//LocationController
public class LocationController : Controller
{
public ActionResult Index()
{
return View();
}
}
In my home controller, I am doing the logic, and then attempting to load the new page.
[HttpPost]
public ActionResult Index(HomeModel model)
{
var proxy = new Proxy();
var r = proxy.GetLocationByAddress(model.SearchString, o.ToString());
if(r==null)
{
ViewBag.Error = "Error during search";
return View(model);
}
ViewBag.Error = string.Format("Found {0} at {1}, {2}", r.StreetName, r.Latitude, r.Longitude);
return RedirectToAction("Index", "Location");
}
But when I run it, submit it, step through, it hits the RedirectToAction - but ... the Home screen simply refreshes. I never see the new Location view. What am I doing wrong here? I have't grasped Routes yet... I need to pass a new object to the Location.Index screen to display...
Your route mapping is incorrect, check this out: http://www.asp.net/mvc/tutorials/controllers-and-routing/creating-custom-routes-cs
routes.MapRoute(
"Location",
"Location/{lang}",
new { controller = "Location", action = "Index", lang = "English" });
I don't think so you need to make any changes. As in your case you want to load different controller with its respecting view you need below change only
replace this code return RedirectToAction("Index", "Location");
with this code return Redirect("http://www.yoursite.com/Location/Index");
Your change is like redirection from one page to another therefore you need to put your complete path here
please try & reply if any problem

How to save query values when searching? ASP.NET MVC

I have such an action method:
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Search(String filter, String value, Int32? page) {
var set = new List<Employee>();
switch(filter) {
case "by-name": {
set = this.repository.Get(
e => (e.LastName + " " + e.FirstName + " " + e.MiddleName) == value
).ToList();
break;
}
case "by-empn": {
set = this.repository.Get(
e => e.EmployeeNumber == value
).ToList();
break;
}
default: return RedirectToAction("Search", "Employee");
}
ViewBag.SearchedEmployees = set.Count();
return View(set.ToPagedList(page ?? 1, PageSize));
}
Search view is like this:
#if(Model.Count > 0) {
foreach(var item in Model) {
Html.RenderPartial("Employee.Card", item);
}
#Html.PagedListPager(
Model,
page => Url.Action("Search", new { page = page }),
new PagedListRenderOptions {
LinkToFirstPageFormat = "<< Beginning",
LinkToPreviousPageFormat = "< Back",
LinkToNextPageFormat = "Forth >",
LinkToLastPageFormat = "End >>"
}
)
}
Search form is presented as a partial view:
#using(Html.BeginForm("Search", "Employee", FormMethod.Get, new { #class = "search-form" }))
{
<p>
#Html.TextBox("value")
</p>
<p>
#Html.RadioButton("filter", "by-name", true) By name <br/>
#Html.RadioButton("filter", "by-empn") By empn <br/>
</p>
<p>
<input type="image" src="#Url.Content("~/Content/Images/Search.png")" />
</p>
}
Problem: I have N page links. When I try to go to the second page I face an infinite loop of redirects. That's the way I implemented my action - default case is fired. So filter/value values are null on the second action call? Why?
How do I refactor my search action?
Also how should I configure route for such an action?
Thanks!
EDIT
So should route for the search action look like:
routes.MapRoute(
null,
"{controller}/{action}/Page{page}/filter{filter}/val{value}",
new { controller = "Employee", action = "Search" }
);
?
EDIT 2
So it is possible to write next:
page => Url.Action("Search", new { filter = ViewBag.SearchFilter, value = ViewBag.SearchValue, page = page }),
And inside a controller:
public ActionResult Search(String filter, String value, Int32? page) {
ViewBag.SearchFilter = filter;
ViewBag.SearchValue = value;
// ...
}
Is this right?
So filter/value values are null on the second action call? Why?
Because their corresponding input fields are inside a separate form and are never sent to the server.
You seem to be using some custom Html.PagedListPager helper (the code for which you haven't shown) but I guess that this helper generates the page links as anchors and it simply doesn't take into account any current query string or POSTed values when generating those links. So the href of your pagination link looks like this /SomeController/Search?page=5 instead of the correct one which would take into account those parameters which is /SomeController/Search?page=5&filter=somefilter&value=somevalue.
You can now easily understand why the filter and value parameters in your controller action are always null. It's because you never send them to the server when clicking on the pagination links.
So in order to resolve this issue you could modify this custom HTML helper that you are using to generate the pagination links to include those additional parameters. Or maybe the helper allows you to pass additional parameters? Check the documentation if this is some third party plugin that you are using.

RedirectToAction to the same action but without the route values

I'll show what I'm trying to do with a simple example.
I have the routes
routes.MapRoute("",
"Message",
new { controller = "Home", action = "Index", myEnum = MyEnum.Message});
routes.MapRoute("",
"",
new { controller = "Home", action = "Index" });
And the action
public ActionResult Index(/*other values*/, MyEnum? myEnum = null)
{
// do some logic
var redirectToHomeUrl = userLoggedIn && myEnum.HasValue && myEnum.Value == MyEnum.Message;
if (redirectToHomeUrl)
{
// do some logic
return RedirectToAction("Index"); <-- problem here
}
// Other logic
}
Basically the user gets sent to mysite.com/Message and is logged out and shown a model dialogue message over the home page. When they act on this message and log back in, the page reloads. I detect that they still have the url for the message and want to redirect them back to the home url "mysite.com/".
However return RedirectToAction("Index") still retains myEnum = MyEnum.Message.
RouteData is persisted after the redirect so I get an infinite loop.
I've tried RedirectToRoute(null, new { action = "Index", controller = "Home"});
I've tried RedirectToAction("Index", new {})
I've tried RouteData.Values.Clear()
I've tried RouteData.Values["myEnum"] = null;
If your wondering RedirectToAction("Index", new { myEnum = null }) doesn't compile :)
Any idea's on how to redirect to the same Action but removing existing route values?
Cheers in advance.
RedirectToAction("Index", new { myEnum = null })
might not compile, but this does:
RedirectToAction("Index", new { myEnum = (MyEnum?)null })
if you're wondering :)
I don't get the point of redirecting to the same action though. If all you want is to remove a value, set it to null manually (or ignore it). If you actually want to call a different function (but the same action) (doesn't seem to be the case, but who knows), just return that function's result from yours directly.

Categories