How to test HtmlHelpers that call Partial? - asp.net-mvc-3

I've been looking at this Stackoverflow question and have the answer implemented. It works all fine and dandy until I get to call HtmlHelper.Partial in my helper method, which is listed below. I know it might not be the best code, but this is until I can refactor more of the app. The error it throws is
Previous method 'ViewContext.get_TempData();' requires a return value or an exception to throw.
Am I missing mocking something, or is there a better way to render a usercontrol?
Edit Ok I did miss something, I didn't call mocks.Replay(). Now have another error which it wants something named controller in routeData...progress.
Edit #2 Clarifying I'm trying to mock the call to HtmlHelper.Partial(partialPath, model), I just want that to return whatever partialPath I send in I suppose, or at least not blowup. I did find this page http://andrevianna.com/blog/?p=8 which was very helpful and I almost got things working. This was helpful as well http://farm-fresh-code.blogspot.com/2009/10/mocking-htmlhelper-class-with.html
public static string RenderRateDetails(this HtmlHelper html, string partialPath, RatesViewData model, RateDetailType type)
{
switch (type)
{
case RateDetailType.AR:
if (model.ExistingRateDetailAR != null)
return html.Partial(partialPath, model).ToString();
break;
case RateDetailType.AP:
if (model.ExistingRateDetail != null)
return html.Partial(partialPath, model).ToString();
break;
}
return string.Empty;
}

I think the example given at 'farm fresh code' is the right way to go, you can't directly mock the HtmlHelper, but you can build an instance where all of it's dependencies are mocked.
When you're code calls html.Partial(partialPath, model).ToString(), the HtmlHelper calls properties and methods on the dependencies that you mocked, and you get errors if these don't return reasonable default values.
In this case it looks like the TemplateData property of the mocked ViewContext object was called, and I imagine it returned null, hence:
Previous method 'ViewContext.get_TempData();' requires a return value or an exception to throw.
Once you mock this property, you should be able to get past this error, but you might need to mock a few more things before you get it all working.
It might save you some time to take a look at the MVC source code to see what gets called in the Partial method. You can get that here http://aspnet.codeplex.com/releases/view/58781.
EDIT
BTW. The TempData property returns a System.Web.Mvc.TempDataDictionary. Mocking the property to return an empty instance of one of those should solve the immediate problem.

Have you considered using Display and Editor templates for your user controls rather than extending HtmlHelper?
I used to do the same thing quite a lot in the early MVC versions, but I have switched almost completely to using templates now.

Related

Can anyone explain the purpose and resolution of CA1822 on a Controller Action?

Error CA1822 : Microsoft.Performance : The 'this' parameter (or 'Me'
in Visual Basic) of 'SomeController.AnAction(string, string)' is never
used. Mark the member as static (or Shared in Visual Basic) or use
'this'/'Me' in the method body or at least one property accessor, if
appropriate.
A static action yields 404 not found when requested via URL. The action is working as expected with code analysis turned off. What's the point of this and what's the appropriate remedy?
Note that the return type of the action is PartialViewResult, it doesn't seem as though code analysis complains about this if the return type is ActionResult.
[HttpPost]
public PartialViewResult BlankEditorRow(string formId, Common.Entities.Common.ObjTypeEnum objType)
{
if (objType == Common.Entities.Common.ObjTypeEnum.Regular)
return new AjaxPartialViewResult("_RowEditor", new ProcedureEntryEntity()) { UpdateValidationForFormId = formId };
else
return new AjaxPartialViewResult("_TemplateRowEditor", new ProcedureEntryEntity()) { UpdateValidationForFormId = formId };
}
Update: Looks like changing the return type to ActionResult resolves the error, and PartialViewResult is an ActionResult so it should work.
I doubt that changing the return type without calling using any instance members really resolves the problem. I suspect that in order to change the return type, you changed the return statement to something which accessed an instance member.
Now I don't know whether the route handling in MVC will let you mark the method as static, but it's worth investigating. Even though the warning is given in terms of performance, I would think of it in terms of intent and readability.
Typically there are two reasons for a method or property to be an instance member (rather than static):
It needs to access another instance member, because the way it behaves depends on the state of the object
It needs to behave polymorphically based on the actual type of the instance it's called on, so that the behaviour can be overridden
If neither of these is the case, then the method can be made static which indicates that there's no polymorphism expected and no instance state required. A static member effectively advertises that the only state it depends upon is the state of the type itself (and the parameters), and that it won't behave polymorphically. Aside from anything else, that means you can test it without creating an instance at all, too.
Of course, if MVC's infrastructure requires it to be an instance method, then you should just suppress the warning, with a comment to indicate that fact.
I think CA just does not take into account that this is a controller action in MVC app. I would suppress.

Is there a preferred way to resolve CA1062 for MVC controller actions?

Running code analysis on the following action results in a CA1062 warning, advising I validate the parameter before using it:
[HttpPost]
public ActionResult Index(SomeViewModel vm)
{
if (!ModelState.IsValid)
return View(vm);
// ... other code
return View(vm);
}
I realize I could resolve the warning by adding:
if(vm==null)
throw new ArgumentNullException("vm");
I was under the impression that if default model binding succeeded the incoming parameter could never be null and would not need to be validated beyond "ModelState.IsValid".
Is that the case?
Is there a widely accepted technique for addressing this warning for MVC actions?
It is a public method, so you shouldn't be making assumptions about who will be calling it. While one caller (the MVC framework) might only invoke the method with non-null values, other potential callers might not be quite so "polite".
That said, if your code does not have other potential callers (which wouldn't be unusual for an MVC application, as opposed to a library), allowing a NullReferenceException to be thrown instead of an ArgumentNullException might be perfectly acceptable. That would depend largely on your expectations for future use and maintainability of the code base. (Amongst other things, a future maintenance developer would probably find it easier to identify a problem if it's signalled via an ArgumentNullException.)
I think that the model parameter can be null during development when MVC is not able to do the mapping, but I suppose that it shouldn't during normal operation.
In my opinion it is not bad to check your parameter as the warning points out.

Confused with Uncle Bob explanation on handling Null objects in book Clean Code

I was reading Uncle Bob book today on Exception handling and what I could recollect from handing null values was that methods should not be handling null values because it clutters the code. I am a little confused with it.
I have always thought that a method should always make sure that it's dependencies are not null (unless they are injected in constructor and constructor assures of nullability).
For example, if I have a method
public void SendMessage(IEmailSender emailSender, contactList list)
{
if(emailSender == null)
{
throw new ArgumentNullException("Failed to send
message.",MethodBase.GetCurrentMethod().GetParameters[0].Name);
}
if(list == null)
{
throw new ArgumentNullException("Failed to send
message.",MethodBase.GetCurrentMethod().GetParameters[1].Name);
}
// rest of code goes here
}
Am I missing something?
There are two perspectives:
On the one hand, with your approach you would always tell the caller what exactly he did wrong by calling your method. Which is great for the caller because he can fix it right away when he gets your exception. This would be true and valid if you where writing API code that is used by a third party.
On the other hand, if you call your method yourself, a reasonable argument to throw an exception is, because you want to be able to handle this situation with a catch block inside your calling code! If you have no reason to handle it somewhere, why throwing an exception at all? The only reason i see is, to have a detailed error logging by catching those exceptions in a GlobalExceptionHandler.
So you see we have two categories of exceptions here: The one for developers, to avoid wrong usage of APIs, and the other one to be used as the method's error-result.
If you are writing API code that will be used by others, your choice would be, not to listen to Bob ;-)
For those who did not read CleanCode, Bob is suggesting two things:
1.You should not write methods that return null (To avoid unnecessary checks afterwards). So Instead of writing this:
var myObject = GetObjectThatDoesSomthing();
if(myObject != null)
{
myObject.DoSomething();
}
... you should be able to write this:
var myObject = GetObjectThatDoesSomething();
myObject.DoSomething();
Cleaner.
2.You should not pass null to your methods to avoid unnecessary checks at the beginning of a method, like here:
public Point Add(Point p1, Point p2)
{
if(p1 == null) throw ArgumentException();
if(p2 == null) throw ArgumentException();
...
}
The point of these rules is: if you stick with it, you know that you dont have to write these null-checks and your code gets cleaner and easier to read. But at the moment you are using third party code, you are not able to tell if they have applied the same rules in their API, so you are starting to pre- or postcheck again. The same thing when you write an API for others: How do the consumers of your API know that you have coded with Bobs rules in mind...
I haven't read the book but I can only imagine that Uncle Bob is advocating the use of the Null Object Pattern in preference to explicit null reference handling.
for example, rather than
if(log != null)
log.Write("My log message");
You could instead create an ILogger interface containing a Write method and create two classes that implement this interface: a NullLogger and a FileLogger. The NullLogger would have an empty body for the Write method's implementation.
In my mind this is different to your explicit pre-condition validation that you have in your example
It depends what type of code are you writing.
If your public method is designed to be used by the wide range of developers non familiar with usage it makes always sense to check parameters and throw a verbose exception.
If you are writing a private method which is only used from the same class or some internal called by another friendly class also written by you or by your collaborator it makes less sense to make paranoia null checks. Your injection design and tests must ensure your internas are not getting null values.
And if private/internal method parameters still get nulls it is anyway too late. Throwing ArgumentNull exception form a private/internal method does not help external user to fix the cause, so it makes no difference for him either to get ArgumentNull or NullReference exception.

wicket: how to update a component after AjaxLazyLoadPanel?

I have a page that has a status text label and a panel doing some DB query. since the query can take some time I am loading it using
add(new AjaxLazyLoadPanel("resultPanel")
{
#Override
public Component getLazyLoadComponent(String id) {
return new SearchResultPanel(id);
}
};
which works very well.
My question is how to update the status label which is outside of the resultPanel, to show the number of search results?
I was thinking along the lines of addComonent(target) but I don't have a target? am i off the track?
Well the SearchResultPanel might look like this:
public class SearchResultPanel extends Panel implements IHeaderContributor{
public SearchResultPanel(String id){
super(id);
....
}
public void renderHead(IHeaderResponse response){
response.renderOnDomReadyJavascript("alert('hello');");
}
}
Now when it is loaded it should throw out that javascript. Another way answered on stackoverflow previously (though I do not like it) is to use an AjaxSelfUpdatingTimerBehavior, which unless the javascript should be ran more then once I do not like, and still it is less elegant in my opinion.
Look here for their answer: Wicket: reload AjaxLazyLoadPanel automatically
You can always obtain the current request target using RequestCycle.get().getRequestTarget(), provided that there is an active request cycle, so in theory you could do that from your lazy-loaded component constructor, check if it is an Ajax target, and add the component if it is.
Another solution is to look at the source code of AjaxLazyLoadPanel and create your own component based on it. (It's really simple but as you can see if you look at the code, there's no way you can make it expose the request target. This isn't a very OO thing to do, but as all the important functionality is wrapped in the constructor, you have very little choice..
I would avoid having to tamper with Javascript, unless there's really no other way.
Happened to come across this post and I have something to add as well.
The AjaxLazyLoadPanel now has an overridable method called onComponentLoaded(Component, AjaxRequestTarget) which could also solve your problem.

Castle.Windsor, ASP.NET MVC, Handling Null Resolution of Injection

Using Castle.Windsor in ASP.NET MVC (3.0) is there any way I can appropriately handle if one of my dependencies resolves null? For instance, say I have a IMembershipService.
class ServiceInstaller
{
// ...
void Install( // .. )
{
container.Register(
Component
.For<IMembershipService>()
.ImplementedBy<MembershipService>()
.LifeStyle.PerWebRequest
);
}
}
Okay, this works great. Now, perhaps not all of my site requires a user to be logged in. Let's assume that maybe my web host's database server crashes for a few hours. In that event, things that looked into the database, or tried to call on my ISession might return null.
What can I do in this case? I can write if(membershipService == null) a hundred times over, but that seems pretty dumb. Is there a built-in solution to say "Hey, if we have an error, do this..?"
I think that the service should never be null. If the database is down, the service should be returned nevertheless, but its methods should throw an exception, return null or some default value, depending on the semantic of the service.
Ciel, i had this problem just recently and found your question while looking for the answer.
Basically you should be using a typed factory to resolve your components at runtime in your wrapping component. The factory should return a default object if there is no match regarding the component you're looking for, default object that would implement whatever behavior is needed.
In the case of your IMembershipService, implement a NotCheckingMembershipService class inheriting the interface and doing nothing and make it the default for the components that won't need it. More specific membership services can be linked to specific controllers.
To do so you must create a generic "catch-all" implementation
public class NotCheckingMembershipService<T>: IMembershipService<T> where T: Controller
{
}
And register it as the default component for an open IMembershipService
_container.Register(
Component.For(typeof(IMembershipService<>))
.ImplementedBy(typeof(NotCheckingMembershipService<>))
.IsDefault());
Then simply register your custom membership services where needed. Resolution won't fail and you will always be able to call the interface.

Resources