I need a HtmlHelper instance in my controller.
How can I instantiate one? thanks
This does not build:
var h = new HtmlHelper(new ViewContext(ControllerContext, new WebFormView("omg"), new ViewDataDictionary(), new TempDataDictionary()), new ViewPage());
Here is a screenshot of the error
Also, when I look at the list of methods under var h, I only see my custom extension methods and no regular ones like ActionLink. So that one needs to list as well. (solved by sternr)
Solution:
Ensure System.Web.Mvc.Html is included.
Here is the code to instantiate a HtmlHelper.
System.IO.TextWriter writer = new System.IO.StringWriter();
var html = new HtmlHelper(new ViewContext(ControllerContext, new WebFormView(ControllerContext, "omg"), new ViewDataDictionary(), new TempDataDictionary(), writer), new ViewPage());
HtmlHelper.ActionLink and most of the methods you'r probably looking for are extension methods declared under the System.Web.Mvc.Html namespace.
As for instantiating\using HtmlHelper inside your controller - this is a bad practice as your clearly combine UI code with Controller code. What are you trying to acheive?
Related
I was trying to work with the http context (with the help of Httpcontext.current) in the application_start event in global.asax then you will receive an Error:- HttpContext.Current Request is not available in this context.
The problem can easily be worked with a workaround by using a static constructor, which is fired when the object is accessed first. We can keep a flag in the Application_Beginrequest event and easily determine the request that initialized the application.
But in this case it gets created at every request, which is not required for me. I want to create or access Httpcontext.current once
My Code Is as Follows :-
`//var context = new HttpContextWrapper(HttpContext.Current);
//var routeData = RouteTable.Routes.GetRouteData(context) ?? new RouteData();
//var requestContext = new RequestContext(context, routeData);
//var urlHelper = new UrlHelper(requestContext);
//var url = urlHelper.Action("Home", "Index");
var httpContext = new HttpContextWrapper(HttpContext.Current);
UrlHelper urlHelper = new UrlHelper(new RequestContext(httpContext, new RouteData()));
if (urlHelper.RequestContext.HttpContext.Request.IsLocal)
{
}
//if (((requestContext.HttpContext).Request).IsLocal)
//{
//}`
There is no HttpContext nor HttpRequest instance in App_Start in integrated mode. You must work around this. If you really need to do something on first request, then register new BeginRequest handler in your global.asax and then unregister it when you are done.
I'm sending an email from my ASP.NET MVC app using the Spark View Engine based on this example by Andrew Kharlamov.
I've setup a unit test, CanSendEmail, but I need to specify the viewfolder in the config.
I found the documentation here and the examples give this:
<spark>
<views>
<add name="{any-unique-name}"
folderType="FileSystem|EmbeddedResource|VirtualPathProvider|Custom"
type="{name, assembly of IViewFolder type}"
constuctor-param-names="values"
subfolder="{optional subfolder to target}"/>
</views>
</spark>
My question is this. Which folderType do I use and do I need any other parameters. My test product is call myProject.Tests and my web project containing the views is called myProject.Web with a Views folder in it.
Do I use FileSystem, VirtualPathProvider ... ?
Edit [14/11/2011]:
Okay I've got this in my app.config in myProject.Tests:
<views>
<add name="web-view-folder"
folderType="VirtualPathProvider"
virtualBaseDir="~/Views"/>
</views>
I still get "View source file not found." when I run my test. I want the test to use the Views in myproject.Web.
My Solution
Based on the blog posts here and here, and with help from #RobertTheGrey and looking at the tests in the Spark source code, I ended up using ViewFolderType.FileSystem. That worked.
Here's the my code under test:
public string RenderEmailWithCustomViewFolder(string sparkViewName, ViewDataDictionary viewData, Dictionary<string, string> viewFolderParameters)
{
var settings = new SparkSettings()
.SetPageBaseType(typeof (SparkView))
.AddViewFolder(ViewFolderType.FileSystem, viewFolderParameters)
.AddAssembly("MvcContrib");
var engine = new SparkViewEngine(settings);
var sparkViewDescriptor = new SparkViewDescriptor().AddTemplate(sparkViewName);
var view = (SparkView)engine.CreateInstance(sparkViewDescriptor);
try
{
// Merge view data
viewData.Keys.ToList().ForEach(x => view.ViewData[x] = viewData[x]);
// Render the view to a text writer
var writer = new StringWriter();
view.RenderView(writer);
return writer.ToString();
}
finally
{
engine.ReleaseInstance(view);
}
}
And here's my test:
[Test]
public void Can_Render_Order_Confirmation_Email_With_Spark_View_Engine()
{
// Arrange
var order = OrderInstanceFactory.CreateTestOrder();
order.ContactEmail = "test#testicle.com";
var emailService = new EmailService();
var viewData = new ViewDataDictionary();
viewData["Order"] = order;
const string viewFolder = #"../../../../app/myProject.Web/Views";
var viewFolderParameters = new Dictionary<string, string> {{"basePath", viewFolder}};
// Act
var emailBody = emailService.RenderEmailWithCustomViewFolder("Email/OrderConfirmation.spark", viewData, viewFolderParameters);
// Assert
Assert.IsNotNull(emailBody);
Assert.IsTrue(emailBody.Contains("test#testicle.com"));
}
My OrderConfirmation.spark template lives in my web products in the Views/Email/.
If it's an ASP.NET MVC app, then you can use VirtualPathProvider since that hooks into the HttpContext and the rest of the runtime. You would use a FileSystemProvider if you were runnig it from a console app for example, or if you wanted to add a folder from outside your web app, perhaps because the templates were shared by other apps, but I've rarely seen that done.
Hope that helps...
I am trying for custom error handling at global level in Application_Error.
Exception ex = Server.GetLastError();
Server.ClearError();
AssortmentDefinitionLogManager.LogException(ex);
Context.RewritePath("/Error/Error");
IHttpHandler httpHandler = new MvcHttpHandler();
httpHandler.ProcessRequest(Context);
But i get this error
Error Message - The view '~/Views/Shared/Error' or its master was not found or no view engine supports the searched locations.
I have also tried this
var urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext);
var redirectUrl = urlHelper.Action("Error", "Error");
Response.Redirect(redirectUrl);
create a controller called ErrorController and inside this controller create an action method called Error which returns an ActionResult (or ViewResult).
Then create a view under ~/Views/Error/ called error.cshtml.
This will solve your problem.
Does anyone know how to get the current RequestContext from the Application_Error event in global.asax?? My problem is that i need to do a redirect, and thereby need to have the url generated using UrlHelper - which takes the aformentioned RequestContext.
While there is no direct way of accessing the RequestContext, you can create one yourself:
RequestContext context = new RequestContext(new HttpContextWrapper(HttpContext.Current), RouteTable.Routes.GetRouteData(new HttpContextWrapper(HttpContext.Current)))
So the UrlHelper can be constructed via:
UrlHelper helper = new UrlHelper(new RequestContext(new HttpContextWrapper(HttpContext.Current), RouteTable.Routes.GetRouteData(new HttpContextWrapper(HttpContext.Current))));
Not pretty, but it gets the job done.
You can access the request context using
HttpContext.Current.Request.RequestContext
Or, if you're in the Global.asax you can use
Context.Request.RequestContext
directly.
Create an HttpContextBase from the Current HttpContext, and from that you can generate a UrlHelper:
// Create Http Context Base from current Context
var contextBase = new System.Web.HttpContextWrapper(System.Web.HttpContext.Current);
// Get its request context
System.Web.Routing.RequestContext requestContext = contextBase.Request.RequestContext;
// Build url helper from request context
var urlHelper = new System.Web.Mvc.UrlHelper(requestContext);
I am trying to create a new contact using Dynamic Entity. The sample i found in CRM SDK had this code.
// Set the properties of the contact using property objects.
StringProperty firstname = new StringProperty();
firstname.Name = "firstname";
firstname.Value = "Jesper";
StringProperty lastname = new StringProperty();
lastname.Name = "lastname";
lastname.Value = "Aaberg";
// Create the DynamicEntity object.
DynamicEntity contactEntity = new DynamicEntity();
// Set the name of the entity type.
contactEntity.Name = EntityName.contact.ToString();
// Set the properties of the contact.
contactEntity.Properties = new Property[] {firstname, lastname};
In my code i have the following implementation.
StringProperty sp_Field1 = new StringProperty("Field1","Value1");
StringProperty sp_Field2 = new StringProperty("Field2","Value1");
CrmService service = new CrmService();
service.Credentials = System.Net.CredentialCache.DefaultCredentials;
// Create the DynamicEntity object.
DynamicEntity contactEntity = new DynamicEntity();
// Set the name of the entity type.
contactEntity.Name = EntityName.contact.ToString();
// Set the properties of the contact.
contactEntity.Properties = new Property[] {sp_Field1,sp_Field2};
I don't see much differences in the code. In the examples i found in the internet i have the same implementation as i found in SDK. But if i run the same i get the following error
CS0029: Cannot implicitly convert type 'Microsoft.Crm.Sdk.StringProperty' to 'Microsoft.Crm.Sdk.PropertyCollection'
I tried created a new variable of type PropertyCollection(one that belongs in mscrm namespace) and added the stringpropertys into that and passed it to the entity.
Microsoft.Crm.Sdk.PropertyCollection propTest = new Microsoft.Crm.Sdk.PropertyCollection();
propTest.Add(sp_SSNNo);
propTest.Add(sp_FirstName);
contactEntity.Properties = new Property[] {propTest};
This gave me the following error
CS0029: Cannot implicitly convert type 'Microsoft.Crm.Sdk.PropertyCollection' to 'Microsoft.Crm.Sdk.Property'
I am sure its a minor typecasting error but i am not able to figure out where the error is. And moreover, even if it was a typecasting error why is it working for all the samples given in the internet and not for me. I tried getting the code sample to run but i am encountering the same conversion error. Please let me know if you need more info on this, any help on this would be appreciated.
Here is an article from Microsoft that makes an attempt to discuss this topic:
http://community.dynamics.com/blogs/cscrmblog/archive/2008/06/23/web-services-amp-dlls-or-what-s-up-with-all-the-duplicate-classes.aspx
This is not a bug that you are running into but more of a difference in design between the way the two assemblies work and what they are designed to do.
If you want to continue to use the Microsoft.Crm.Sdk.dll you should be able to accomplish your goal with the following...
StringProperty sp_Field1 = new StringProperty("Field1","Value1");
StringProperty sp_Field2 = new StringProperty("Field2","Value1");
CrmService service = new CrmService();
service.Credentials = System.Net.CredentialCache.DefaultCredentials;
// Create the DynamicEntity object.
DynamicEntity contactEntity = new DynamicEntity();
// Set the name of the entity type.
contactEntity.Name = EntityName.contact.ToString();
// Set the properties of the contact.
PropertyCollection properties = new PropertyCollection();
properties.Add(sp_Field1);
contactEntity.Properties = properties;
Thanks SaaS Developer, that code is working fine now. One more way of doing it would be to directly add the StringProperty to the entity property collection.
contactEntity.Properties.Add(sp_SSNNo);
Thanks again for replying :)
I believe the issue is that you are referencing the dynamic entity class in the Microsoft.Crm.Sdk assembly. The sample in the SDK is using a reference to the CRM web service. This can get confusing as both assemblies contain many of the same types, however they are different.