I have followed the blog post written by Steve Sanderson at blog.codeville.net/2008/10/14/partial-requests-in-aspnet-mvc. It all work fine when follow it exactly but I was hoping that someone may have looked at it and be able to assist me in adapting it slightly.
I basically have this "partial request" calling from one controller to another and this works fine. I then want to foreach through the data and create a drop down list. The problem is that I need to convert it to an IEnumerable to do this but it fails telling me that I cannot convert a void to an IEnumerable.
The lkine fails on is in the view and is:
foreach (var category in (IEnumerable<MyObject>) ((PartialRequest)ViewData["ReturnedData"]).Invoke(ViewContext))
Clearly, knowing how to answer this is hard without seeing the code. This is all in the aforementioned post but as it is reasonably lengthy I do not want to post it all in here. I understand that this makes answering this difficult and am hoping that someone has ready that post and can assist.
Thanks in advance.
The PartialRequest Invoke method doesn't return anything, it writes the HTML that the request generates to the response. The idea is that you can invoke a controller action that renders an MVC View User Control rather than a View. You can make a partial request to this controller action and have it render the control directly into the response stream rather than using the Html.RenderPartial. Since the control writes directly to the response, you don't have a chance to interact with it's output.
Related
So I am a newbie grails developer, and was wondering how to properly use services per the MVCS design pattern. Right now in my service, I have a couple functions doing my application logic, and then I am referencing the service directly from my gsp. I read on a comment here that this is not good form. So right now I have
<g:set var="doc" bean="documentPartService"/> directly in my gsp.
So I am looking to change it, just like the comment states, by passing the information through the right channels.
One little hurdle I am coming across is passing information from my service to my controller to my gsp. For an example
<g:form name="inputForm" action="replace">
somecodehere...
<input value="Submit" type="submit">
</g:form>
then in my replace function in my controller
def replace(){
render documentPartService.replace(params)
}
then I have some logic in my service.
I have seen in some services I have looked at, they return the variable as a json (documentBody is a variable local to my service)
return documentBody as JSON
but I am a little puzzled on how to actually access this in my controller/view. I can't just
print documentBody in my controller, because it is only defined in my service. In the plugin services and controllers I was using as references, the controllers are 1 liners, just like I have, where the only thing they do is render servicefunction()
Can anyone shed some light on how I should properly design this?
When you post your form the action is replace - the replace action in your controller renders the output of your service back out as the output rather than returning a gsp bound to the replace controller definition.
In theory it should work as in the user will post - the post will return the action replace which will return that JSON response.
the alternative is
def replace(){
def myValue=documentPartService.replace(params)
render (view: 'replace', model: [myValue:myValue ])
}
then you could have a gsp page called replace which has ${myValue} defined in it which will be its results.
Also its probably a better idea to call your service with defined values passed via the controller to it:
def replace(String val1,String val2,String val3){
def myValue=documentPartService.replace(val1,val2,val3)
[myValue:myValue ]
}
UPDATE
It may seem much coming from me to be hinting the latter method considering you probably seen the first call i.e.
render documentPartService.replace(params)
calls similar to above methods within one of my plugins.. I guess if you took a look at the mailinglist plugin, you will notice with the help of Burt. The controllers/services are locked down to data types and exact expectations.
I can only tell you from experience that best practices are if they are to be defined functions that have no reason for expansion then stick with the latter method. In the case of for example ajaxdependancyselection using the render services output method, in some ways this helps keep it more backward/forward compatible. But actually thinking about it maybe those calls can be locked down. Will update the plugin soon
I have been banging my head over this for the past 3 days (No kidding!!!)....It seems like a very simple thing but I am just unable to do it. So I'm putting the question out here, and am open to any method which would work.
BACKGROUND : An advanced search form on submission used to generate an URL too large for the server. So the form had to be submitted via POST. So far, so good. Form submitted successfully, and the result was displayed. Only remaining problem was pagination.
As it's a POST call, it ruled out will pagination. While will-pagination merges param page to the existing params, but the problem is that it shows on url which results in the same error.
QUESTION: So is there any way, if the user clicks a link NEXT, I can
a) Update the page param
b) Keep the existing params
c) While not changing the URL
d) Transfer control back to the action in controller?
The only solution so far suggested was have a hidden form, repopulate it's value and submit again. The form's pretty complex, so if there is a cleaner way I'd like to know.
I see what you want from your comment. So editing my reply accordingly. You want the information as to which column is being selected in the sort to be available to the controller without having that information available in the url string, and you want to use GET for this not POST
The challenge you have is that you want to preserve state between requests and you need a mechanism for doing this. POST preserves that information by sending it in the body of the POST request. GET does this by allowing you to populate the query string. The other method for preserving state is to use a cookie.
You can manipulate the url with javascript on the page. There are tutorials online for that.
But if you just want a simple controller hack as you say in your comment then the simplest one I can think of is to allow the user to make the GET request to the url with the query params in it, then handle this request in two steps - step one saves the query information to the cookie, step two redirects them to the url with that query string data stripped, and you look on the cookie to see if it has those fields before building your data for that page. It's hacky but it works.
def sort
session[:sort] = params[:sort]
redirect_to url_without_the_query_string
end
There is also the new html 5 feature:
window.history.replaceState(“Replace”, “Page Title”, “/mypage”);
from this stackoverflow answer here: How to remove query string from url using javascript
However I'm not sure I'd recommend messing with the url after load like that (I don't know enough about that solution so I'd recommend you read that answer and see if that fits). So, if you MUST lose that data from the url string, because you need to somehow pass it between requests you either have to use POST, or use the session cookie/redirect method I describe above.
Does your html <form> have an action attribute? If not, add one that points to the page.
If you want to preserve the current GET params so that results from the POST can use , you will also need to modify the javascript triggered on the heading links so that as well as (or instead of) modifying the query string, they write the same data to hidden form fields (which of course then get posted in the body of the request). Your JS library may already include helpful functions for that.
Trying to find help for this problem has taken me to a whole new one: complete lack of ressources, books and samples vor MVC 4 in VB.NET. I am having to choose between learn by experience (and the associated feeling of banging your head against a wall) or give it up and move to C# alltogether.
No company should ship a product if they are not willing to give it the same support as its sibling pruduct. They should drop VB for MVC completely or give us the means to learn it.
With that out of the way, here's my question. This line:
#Html.EditorFor(Function(x) x.UsersData(temp).Roles(Role))
Is a nice line of code. Works wonders. But How can I add a class to it, so I can change the style on my css files?
Well, it seems that this should do the trick:
#Html.EditorFor(Function(x) x.UsersData(temp).Roles(Role), New With {.class = "users-manage-check-box"})
But guess what, it doesn't. Ever. The result is the same.
What is wrong and how can I fix it?
And to be completely honest, I did come up with a solution. One that makes me feel dirty.
Looking at the output from that code, i see that the boxes classes are "check-box".
So what I've been doing is this:
#html.Raw(Html.EditorFor(Function(x) x.UsersData(temp).Roles(Role), New With {.class = "users-manage-textbox"}).ToHtmlString.Replace("check-box", "user-manage-checkbox"))
This feels wrong. So wrong. And not only is it a sad piece of code, it introduces security risks, which I'll have to fix before my solution is out of the development phase.
Any clues on why the additional view data is not working as it should? Am I getting something wrong? Am I asking too much?
Thanks a lot!
I don't think EditorFor allows that. So you need to create a custom editor template yourself.
You can read more about creating custom templates in this blog post
Update:
Take a look at the answer for this issue from http://aspnetwebstack.codeplex.com/
This behavior is by design.
The overload that you are calling accepts an object parameter called
additionalViewData (http://msdn.microsoft.com/en-us/library/ff406462).
The default implementation of EditorFor ignores this value. You would
have to write a custom editor template to be able to access that
information.
Spoiler alert: this is NOW a question, so apologies to anyone that read it purely as a discursive topic :)
Anyway, I was doing a little research today re adding routes via javascript when i thought that a bit of google research wouldn't hurt. Basically, my aim was to do away with the following type of construct within my views:
and replace it with something akin to:
well, i lucked out a little today after finding this fantastic article (which isn't mine nor do i have any affiliation other than respect for the piece of work):
http://weblogs.asp.net/zowens/archive/2010/12/20/asp-net-mvc-javascript-routing.aspx
this really has been a missing link (or so i thought) for me when dealing with routes via javascript. However, the 2nd code example is misleading and actually won't produce what the example leads on. Can anyone suggest a fix for this and/or an alternative solution to allow this fluent convention of js routes within mvc views??
cheers...
[edit] - question edited 22:16 GMT to explore deeper options on this topic, plus changed title (removed OT portion).
So the question is why the second code example won't work as expected. Here's the answer, post currently doesn't return anything. This is an example of a certain developer not looking at the details of the code. When you use homePageUrl, the value will be undefined.
To actually get the home page URL, you'd do the following:
$.routeManager.action({controller:'Home', action:'Index'}).toUrl()
So, the moral of the story is that the code is a bit broken. The post action SHOULD return an object where you can put "toUrl()" right after the post is performed, like this:
$.routeManager.action({controller:'Home', action:'Index'})
.post(function(data){ alert(data); })
.toUrl();
I'll be fixing this bug in a bit!
i want to add a hyperlink in my message like
ModelState.AddModelError("_FORM", "Please report this error Click Here");
Im using asp.net mvc 2. How can i do this?
The problem is that the ValidationMessage and ValidationSummary methods internally use the SetInnerText() method which automatically encodes the values you have saved in the Model Errors.
Like queen3 suggests, you'll have to write your own versions of these methods to overcome this.
You can see original methods in the MVC2 source code here.
Replace tagNameHere.SetInnerText(value) with tagNameHere.InnerHtml = value
Important Note: Please make sure you take great care with where the information displayed in these messages comes from, you're allowing html now, so you're susceptible to Cross Site Scripting