How to force one method on Razor ambiguous reference? - asp.net-mvc

On one MVC 4 project, we have a lot of Pages.cshtml that receive a collection of Models (generally hundreds of rows), which we serialize as JSON via
#Html.Raw(Json.Encode(Model));
The problem is that on some of those pages we are receiving an exception (The length of the string exceeds the value set on the maxJsonLength).
We know what is the reason and how to fix it. The thing is that I would like to create a similar Json.Encode() method (using Json.Net), so we do not need to modify all the cshtml pages. If I create a Json.Encode() method, Razor complains about ambiguous reference between My.Namespace.Json and System.Web.Helpers.Json.
Again, we know how to solve this by adding an alias on the page:
#using Json = My.Alias.Json
What I'm trying to do is to transparently instruct Razor to choose this alias for all the cshtml pages that uses this Json.Encode. The reason is that I want this to be transparent, so later if somebody adds a new page, automatically he will start to use our custom JSON implementation.
I think on Views/Web.config you can add namespaces and some configurations for Razor, but I don't see how to explicitly set the aliases.

Interesting issue, but as far as I know that's not possible. See e.g. this: C#: Globally alias a generic class name?
As an alternative you could create a helper method Html.JsonEncode() and teach, drill or entice everyone to use that.
If you make it also do the Raw() call and return IHtmlString, then you can do #Html.JsonEncode(Model) as opposed to #Html.Raw(Html.JsonEncode(Model)) and before you know it everybody is a fan of your new method.

Related

Define the controller namespace based on URL parameter

I'm working on a Web API with MVC4, and I'd like to make it backwards-compatible, as I don't control when the clients are updated.
In order to do that, I'm going to create controllers on different namespaces, something like MyApp.Controllers.v1_0.AccountsController and MyApp.Controllers.v1_1.AccountsController
Obviously, when I create both of them and try to access to an action, I get "Multiple types were found that match the controller named 'Accounts'"
Then, what I tried to do is writing my own IHttpControllerActivator, so that when Create is invoked, it returns one of them... but that doesn't work b/c it never gets hit, which makes sense as Create receives an System.Web.Http.Controllers.HttpControllerDescriptor that includes information about the controller it's about to use.
Also, I can't just name the controllers different (Accounts1_0Controller, Accounts1_1Controller), as when the activators returns Accounts1_0Controller, it says that its name is not "Accounts"... it probably gets its name as Accounts1_0.
Do you see any way of either:
Set the namespace from the url? so that I have the url /v1_0/SomeAction or /v1_1/SomeAction and it searches the controller on the appropriate namespace
Having multiple controllers with the same MVC name but different class name?
Hope the issue is clear enough.
Thanks!
Fixed it implementing my own IHttpControllerSelector. It's great how Microsoft made MVC4 open source, made it almost painlessly looking at their System.Web.Http.Dispatcher.DefaultHttpControllerSelector.

MVC: Set Name Attribute w/Helper

I have a situation in an MVC3 app where I would like to be able to set the name attribute on some html being generated by a helper (DropDownList).
It appears this is not possible. Apparently the helpers silently override whatever value you may specify for the name attribute in the html attribute object that you pass to the helper.
I'd like to confirm that before I waste too much more time on trying to work with the existing helpers.
And, as an aside, if it is not possible by design...I think that's a foolish limitation in the MVC framework. Yes, I know that assigning the wrong name attribute can break the automatic model binding. But I should be able to do that when I need to. After all, I can always write the raw html using whatever name attribute I chose. The helpers should help, not be a straitjacket.
Edit to discuss whether editor templates maintain navigational context
Darin, I am using editor templates (I was using the term "partial" generically, since editor templates are a special kind of partial view).
Editor templates do modify the HtmlFieldPrefix -- that's how I noticed I had a problem :). I was using a call like this:
// call in higher level partial - context is 'eae'
#Html.EditorFor(m => m.Value)
...
// inside editor template for typeof(Value) context is 'eae:Value'
That context shift is needed to keep the default binding mechanism working properly. I'm using a different approach, where I want the context to stay fixed throughout a call chain of partials (i.e., as execution burrows down into deeper partials I want the context to stay the same).
This is by design. The HTML helpers do not allow you to override the name attribute. They generate the name based on your view model so that the default model binder is able to properly bind the values according to the well established conventions when the form is submitted.
And, as an aside, if it is not possible by design...I think that's a
foolish limitation in the MVC framework.
You could open a ticket on MS Connect and hope this could change in a future version of the framework. Until then you could also write your own custom helpers that will allow you to override the name attribute for the cases when you need such functionality. Personally I've never needed it so far but I am sure you have valid reasons. Another possibility is to write a custom model binder on the server.

Can I use a MVC Global Action Filter to disable form fields?

Some users of our application will have read-only access to many of our pages, in our current web forms app this means they see the form, but all of the fields are disabled. We're looking at MVC 3 and searching for the cleanest, most idiomatic way of implementing this functionality.
Some ideas so far:
Some combination of a global action filter and edit templates.
A custom Html helper, something like Html.SecureTextBox etc...
I'm leaning towards number 1, but I'm wondering if any of you guys/gals with more MVC experience have solved this problem in a better way.
I agree with using a base view model, or perhaps just an interface with a "CanEdit" type of property. If you go the interface route, you could set the property in an ActionFilter in the OnActionExecuted method.
To tie it to the view, creating a new HtmlHelper would be pretty easy. I'd use TextBoxFor as the base class, since it has access to the view's model. You can then inspect the property and create the necessary HTML attribute. However, with going this route you will need to create a new helper for each type of input control you need (textbox, select list, etc).
Without knowing all the details of what you are doing, a much simpler idea would be to not provide a Save button for read-only users. The Save button would be driven by one property in the view model (or ViewData, if you like).
Several other people mentioned that a server-side restriction is still needed to prevent people from bypassing the client-restrictions. You will need an action filter for this. This link has a good idea about that.
My preference would be to set a variable in a common base view model (or ViewData), using a global action filter, and then use a bit of jquery to dynamically disable the input fields, delete buttons etc.
$(':input').attr('readonly', true);

Rails flash hash violation of MVC?

I know Rails' flash hash is nothing new, but I keep running into the same problem with it.
Controllers should be for business logic and db queries, not formatting strings for display to the user. But the flash hash is always set in the controller. This means that I need to hack and work around Rails to use Helpers that I made to format strings for the flash hash.
Is this just a pragmatic compromise to MVC or am I missing something here?
How do you deal with this problem? Or do you not even see it as one?
It appears to be possible to "forcefully" access helpers from controllers. See this discussion here:
http://lojic.com/blog/2007/07/27/using-helpers-inside-controllers-in-ruby-on-rails/
You could also "render" a partial to an instance variable. See this page:
http://snippets.dzone.com/posts/show/396
Normally, if you call "render_partial" within a controller, nothing but the partial will be rendered.
Occasionally, it is useful to render a partial to an instance variable as a string so that the view can still be rendered as
normal, and the string can be passed in to the view.
add_variables_to_assigns
#content_for_navbar = #template.render_partial 'layouts/public_navbar'`
Rails isn't necessarily strictly MVC. In the Rails world, controllers are more like what would otherwise be called View-Controllers in the MVC pattern.
Also, I would argue that in 'pure' MVC, the controllers should not be doing DB queries and business logic—that should be encapsulated in the model layer. Controllers are about moving data between the view and the model.
What about creating helper methods for the view that format whatever you stick into the flash hash? The flash needn't only contain string values; it can contain arbitrary objects. I often find myself putting an array of model validation errors into flash[:error], and writing a helper method to format those messages into a <ul>.
If you'd really like to, you can store a key in the flash variable and then in the view translate that key into an actual message. How the flash displays isn't in any way built-in. It all depends on how much work you are willing to put into it in order to get pure MVC.
The method described by shedd didn’t work for me. The second method described in http://snippets.dzone.com/posts/show/396 did work:
#content_for_navbar = render_to_string :partial => "layouts/public_navbar"

is there any legitimate reason to use ViewData in asp.net mvc

with model binding where you can build up an object to ship and bind to the view, is there any reason to ever use ViewData ?
I can't forsee an instance where I would use it unless I had static information coming in from a database for a page/master that then got displayed in say a <p> or some such.
If the page was a read only page that say returned a list of items and I also wanted to display text from a DB then I might use ViewData.
But that's kind of an exception. If I was returning a list of items from a DB along with some other stuff then I would create a Form View Model and simply include any other data in with it.
So rarely I guess is my answer here.
ViewData seems to exist as a simple, convenient approach to something that you really should do a syntactically cleaner way. The MVC equivalent of an ArrayList I suppose- works just fine but you'd be hard pressed to come up with a truly legitimate excuse for using it in good code.
One exception I can think of for using it would be including something dynamic in ALL of your pages that gets appended in an ActionFilter or base Controller class- for example "WebsiteTitle". Rather than attempting to tamper with the data being returned by a Controller action it might make more sense to include something like that in the ViewData collection- perhaps prefixed with some unique identifier to make it obvious it was being included outside the controller action. ViewData["Base_WebSiteName"], for example.
I am pretty new to MVC but what little I have done, I have written custom objects for all my views.
The only reason I could think of is to save time. You need to whip something up fast and maybe there are multiple objects of data on a page and something extra and you don't want to take the time to write an object putting it all together. Is this a good reason? In my opinion no.

Resources