Model value not set when passing into View in ASP.NET MVC2 - asp.net-mvc-2

Stumped...
I have a few routes set up:
Function AddUpdate(ByVal id As Long) As ActionResult
Return View(New UPDATES With {.ID = id})
End Function
<HttpPost()> _
Function AddUpdate(ByVal Update As UPDATES) As ActionResult
//Do cool posted stuff here
End Function
The type of the .ID is LONG.
When it runs the post function, the Update object's Update.ID is nothing.
My view doesn't alter the property, and I don't have any Helper methods attached to it in the view. Shouldn't it be sent back through to the post method?
Thanks - JB

Is The id being sent back in the HTTP Post (using fiddler or firebug to see)?

Are you actually passing the value back with POST, either through your route, or a form field? The ModelBinder can't bind values if it doesn't know where to look for them...

Related

POST -ing data with Laravel 4's resourceful controller does not work (store method) but works using index (GET) method. What am I doing wrong?

Hi I have a resource controller in Laravel 4. It has all the default methods generated by artisan's controller:make.
Models etc are in place.
User clicks on a link in a view that does a URL::route to a named route pointing at a controller action. It points to the 'store()' method in the controller, which is meant to be a POST method.
I write my code in the 'store()' method to handle this request. It uses eloquent to insert data into db. It returns a plain text response with HTTP code 200.
When user clicks on the above mentioned link (that points to the store() method), it seems the browser simply jumps to the index (GET) of that controller and the code doesn't run because the store() method is bypassed.
When I move all code from within the store() method into the index() method, everything works as expected.
What am I doing wrong here that my 'store()' method is not handling my code. Even when creating URL to the store action directly using URL::action, this fails.
Can someone please enlighten me?
Code:
Store method:
public function store()
{
$itemsArray = Session::get('sdata');
$cartItem = new Cart;
$cartItem->session_id = Session::get('sid');
$cartItem->items = json_encode($itemsArray);
$cartItem->save();
return Response::make('an item was added to carts', 200);
}
View:
Go
Same result for this view also:
`Go`
This is because <a> tag, is able to send only GET request. Try to create a new method, for example addToCart, and then set new rout on routes.php

HTML form POST method with querystring in action URL

Lets say I have a form with method=POST on my page.
Now this form has some basic form elements like textbox, checkbox, etc
It has action URL as http://example.com/someAction.do?param=value
I do understand that this is actually a contradictory thing to do, but my question is will it work in practice.
So my questions are;
Since the form method is POST and I have a querystring as well in my URL (?param=value)
Will it work correctly? i.e. will I be able to retrieve param=value on my receiving page (someAction.do)
Lets say I use Java/JSP to access the values on server side. So what is the way to get the values on server side ? Is the syntax same to access value of param=value as well as for the form elements like textbox/radio button/checkbox, etc ?
1) YES, you will have access to POST and GET variables since your request will contain both. So you can use $_GET["param_name"] and $_POST["param_name"] accordingly.
2) Using JSP you can use the following code for both:
<%= request.getParameter("param_name") %>
If you're using EL (JSP Expression Language), you can also get them in the following way:
${param.param_name}
EDIT: if the param_name is present in both the request QueryString and POST data, both of them will be returned as an array of values, the first one being the QueryString.
In such scenarios, getParameter("param_name) would return the first one of them (as explained here), however both of them can be read using the getParameterValues("param_name") method in the following way:
String[] values = request.getParameterValues("param_name");
For further info, read here.
Yes. You can retrieve these parameters in your action class.
Just you have to make property of same name (param in your case) with there getters and setters.
Sample Code
private String param;
{... getters and setters ...}
when you will do this, the parameters value (passed via URL) will get saved into the getters of that particular property. and through this, you can do whatever you want with that value.
The POST method just hide the submitted form data from the user. He/she can't see what data has been sent to the server, unless a special tool is used.
The GET method allows anybody to see what data it has. You can easily see the data from the URL (ex. By seeing the key-value pairs in the query string).
In other words it is up to you to show the (maybe unimportant) data to the user by using query string in the form action. For example in a data table filter. To keep the current pagination state, you can use domain.com/path.do?page=3 as an action. And you can hide the other data within the form components, like input, textarea, etc.
Both methods can be catched in the server with the same way. For example in Java, by using request.getParameter("page").

Change or switch request data

I'd like to create filter which will switch request data. More precisely i'd like to change type of request inside filter (it have to be POST), add some values into post's Data, add return url, and redirect it to Controller's action which accepts only POST... and then in this action i'd like to return to first URL.
I've found something like...
Response.Redirect with POST instead of Get?
but i'm pretty sure i don't catch his idea completely and don't know is it useful in FIlter.
I've not found how to change request data... but useful was to
var controller = new MyController();
controller.ControllerContext = filterContext.Controller.ControllerContext;
controller.<action>(<parameters>); // it's action which accepts only POST, but here it doesn't matter
base.OnActionExecuting(filterContext);
Is there any better way to pass context or mayby... invoke Controller from current context? instead of creating new controller and calling his action?

TempData["message"] isn't reliable-- what am I doing wrong?

I'm using TempDate["Message"] to show little update banners as the user does things on my site like this:
[AcceptVerbs(HttpVerbs.Post), Authorize(Roles = "Admins")]
public ActionResult Delete(int id)
{
_Repo.DeletePage(id); // soft-delete
TempData["Message"] = "Page deleted!";
return RedirectToAction("Revisions", "Page", new { id = id });
}
Then in my master page I have this:
<%-- message box (show it only if it contains a message) --%>
<% string Message = (TempData["Message"] ?? ViewData["Message"]) as string;
if(!string.IsNullOrEmpty(Message)){
%>
<div id="message"><%:Message %></div>
<% }
TempData["Message"] = null; ViewData["Message"] = null; %>
I hit both TempData and ViewData because I read somewhere that TempData should be used for redirects and ViewData should be used otherwise.
The issue is: often the message won't show up right away. Sometimes it takes a click or two to different parts of the site for the message to show up. It's very strange.
Any ideas?
You should verify all places where you use TempData["Message"] in your code. Corresponds to ASP.NET MVC does browser refresh make TempData useless? you can read TempData["Message"] only once (see also http://forums.asp.net/p/1528070/3694325.aspx). During the first uage of TempData["Message"], the TempData["Message"] will be deleted from the internal TempDataDictionary.
Probably it would be better to use TempData["Message"] only inside of Revisions action of the Page controller and not inside of master page or inside a View.
TempData is not intended to pass data to views, hence the name ViewData for that purpose. In fact, I can't think of a reason to use TempData from within a view definition at all...
One very common usage of TempData is the passing of information between controller actions when you do a redirect (the Revisions action in your example above, for instance, would be able to make use of your TempData["Message"] variable).
This is common practice in the PRG means of coding MVC interactions (Post-Redirect-Get) since you often need to pass information from the initial target action when doing the Redirect to the Get. An example of how this might be useful in a Get is below where I often just default to a new viewmodel UNLESS there is one already passed from a redirect in TempData:
public ActionResult System() {
SystemAdminVM model = (SystemAdminVM)TempData["screenData"] ?? new SystemAdminVM();
One more thing; I see you explicitly clearing your TempData and ViewData dictionary entries in your view. You don't need to do that as by that point they are at the end of their life spans anyway...
Happy coding!
Your app's behavior is the one you'd expect if you're using TempData where you should be using ViewData.
You want to double-check that you're storing your status feedbacks in TempData only when the controller does a re-direct. Otherwise, you should use ViewData.
This smells like you need a couple of unit tests to confirm the behavior you're seeing. Try writing up a couple using this example as a starting point:
http://weblogs.asp.net/leftslipper/archive/2008/04/13/mvc-unit-testing-controller-actions-that-use-tempdata.aspx
If you have configured multiple worker process for your application, but session state mode is "InProc", then you can't use default TempData implementation, as session state becomes unusable. (see ASP.NET session state and multiple worker processes)
You could try to use MvcFutures CookieTempDataProvider instead.

Persisting querystring parameter throughout site in ASP.Net MVC 2

http:www.site1.com/?sid=555
I want to be able to have the sid parameter and value persist whether a form is posted or a link is clicked.
If the user navigates to a view that implements paging, then the other parameters in the querystring should be added after the sid.
http:www.site1.com/?sid=555&page=3
How can I accomplish this in Asp.Net Mvc 2?
[Edit]
The url I mentioned on top would be the entry point of the application, so the sid will be included in the link.
Within the application links like:
<%= Html.ActionLink("Detail", "Detail", new { controller = "User",
id = item.UserId })%>
should go to:
http:www.site1.com/user/detail/3?sid=555
This question is different than what Dave mentions, as the querystring parameter is persisting throughout the site.
Firstly, I'd say if the value needs to be persisted throughout the session then you should store it in Session and check that its still valid on each action call. This can be done through a custom action attribute you add to the controller / actions required. If the value is required then when the value is checked you can re-drect to a login page or similar if not present or its expired.
Anyway, that said I thought I would have a crack at getting it working. My first thought would be to create a custom action filter attribute which took the value of the querstring and stored it in session in OnActionExecuting and then OnResultExecuted would add the key back to the querystring. But as QueryString in Request is a read-only collection you can't do it directly.
So, whats now available to you?
Option #1 - Add it to all calls to Html.ActionLink() manually
or ...
Option #2 - Override a version of ActionLink which automatically adds the value for you. This can be achived like so. I wouldn't recommend doing this though.
Start off with the custom attribute.
public class PersistQueryStringAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var sid = filterContext.RequestContext.HttpContext.Request.QueryString["sid"];
if (!string.IsNullOrEmpty(sid))
{
filterContext.RequestContext.HttpContext.Session["sid"] = sid;
}
base.OnActionExecuting(filterContext);
}
}
All this does is check the request querystring for the required key and if its available add it into the session.
Then you override ActionLink extention method to one of your own which adds the value in.
public static class HtmlHelperExtensions
{
public static MvcHtmlString ActionLink<TModel>(this HtmlHelper<TModel> helper, string text, string action, string controller, object routeValues)
{
var routeValueDictionary = new RouteValueDictionary(routeValues);
if (helper.ViewContext.RequestContext.HttpContext.Session["sid"] != null)
{
routeValueDictionary.Add("sid", helper.ViewContext.RequestContext.HttpContext.Session["sid"]);
}
return helper.ActionLink(text, action, controller, routeValueDictionary, null);
}
}
On each of the action which is going to be called apply the attribute (or apply it to the controller), eg:
[PersistQueryString]
public ActionResult Index()
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
return View();
}
Note
As the query value gets put into session it will be applied for the life of the session. If you want to check that the value is there and the same each request you will need to do some checking in the attribute overridden method.
Finally
I've purely done this as a "can it be done" exercise. I would highly recommend against it.
Possible Duplicate:
How do you persist querystring values in asp.net mvc?
I agree with the accepted answer to the question linked above. Querystring parameters are not designed for data persistence. If a setting (i.e. sid=555) is intended to persist through a session, use Session state or your Model to save that data for use across requests.