T4 reports Compiling transformation: Invalid token 'this' in class, struct - visual-studio-2013

Attempting to run the T4 templates for Immutable Object Graph gives errors of
╔═══════╦═══╦══════════════════════════════════════════════════════════════════════════════════════════════════╦═════════════════════════════════════════════════════════╦═══╦════╦══════╗
║ Error ║ 5 ║ Compiling transformation: Invalid token 'this' in class, struct, or interface member declaration ║ c:\dev\ImmutableObjectGraph-master\2013\Demo\Message.tt ║ 1 ║ 1 ║ Demo ║
║ Error ║ 6 ║ Compiling transformation: Method must have a return type ║ c:\dev\ImmutableObjectGraph-master\2013\Demo\Message.tt ║ 1 ║ 6 ║ Demo ║
║ Error ║ 7 ║ Compiling transformation: Type expected ║ c:\dev\ImmutableObjectGraph-master\2013\Demo\Message.tt ║ 1 ║ 12 ║ Demo ║
╚═══════╩═══╩══════════════════════════════════════════════════════════════════════════════════════════════════╩═════════════════════════════════════════════════════════╩═══╩════╩══════╝
The line reported is always line 1, and the full set of t4 templates is many hundreds of lines. How do I troubleshoot and fix this issue?

You cannot have literals in a T4 template after a scriptlet.
Change
<## template debug="true" language="C#" #>
<#+
// scriptlet
#>
<-- empty line here
To
<## template debug="true" language="C#" #>
<#+
// scriptlet
#>
Debugging
You can see the C# being generated by the T4 engine by calling PreProcessTemplate with a custom templating host.
I modified the Custom Template Host sample for this purpose:
using Microsoft.VisualStudio.TextTemplating;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace CustomHost
{
class CustomCmdLineHost : ITextTemplatingEngineHost
{
public string TemplateFile { get; private set; }
public string FileExtension { get; private set; }
public Encoding FileEncoding { get; private set; }
public CompilerErrorCollection Errors { get; private set; }
public IList<string> StandardAssemblyReferences { get { return new[] { typeof(System.Uri).Assembly.Location }; } }
public IList<string> StandardImports { get { return new string[] { "System" }; } }
public CustomCmdLineHost(string file)
{
this.TemplateFile = file;
this.FileEncoding = Encoding.UTF8;
this.FileExtension = ".txt";
}
public bool LoadIncludeText(string requestFileName, out string content, out string location)
{
content = location = String.Empty;
if (File.Exists(requestFileName))
{
content = File.ReadAllText(requestFileName);
return true;
}
return false;
}
public object GetHostOption(string optionName)
{
object returnObject;
switch (optionName)
{
case "CacheAssemblies":
returnObject = true;
break;
default:
returnObject = null;
break;
}
return returnObject;
}
public string ResolveAssemblyReference(string assemblyReference)
{
return ResolvePath(assemblyReference);
}
public Type ResolveDirectiveProcessor(string processorName)
{
throw new Exception("Directive Processor not found");
}
public string ResolvePath(string fileName)
{
if (File.Exists(fileName))
{
return fileName;
}
string candidate = Path.Combine(Path.GetDirectoryName(this.TemplateFile), fileName);
if (File.Exists(candidate))
{
return candidate;
}
return fileName;
}
public string ResolveParameterValue(string directiveId, string processorName, string parameterName)
{
return String.Empty;
}
public void SetFileExtension(string extension)
{
FileExtension = extension;
}
public void SetOutputEncoding(System.Text.Encoding encoding, bool fromOutputDirective)
{
FileEncoding = encoding;
}
public void LogErrors(CompilerErrorCollection errors)
{
Errors = errors;
}
public AppDomain ProvideTemplatingAppDomain(string content)
{
return AppDomain.CreateDomain("Generation App Domain");
}
}
class Program
{
static void Main(string[] args)
{
var templateFileName = args[0];
CustomCmdLineHost host = new CustomCmdLineHost(templateFileName);
Engine engine = new Engine();
string language;
string[] refs;
var output = engine.PreprocessTemplate(
// input file
File.ReadAllText(templateFileName), host,
"testClass", "testNamespace", out language, out refs);
string outputFileName = Path.Combine(
Path.GetDirectoryName(templateFileName),
templateFileName + ".generator.cs");
File.WriteAllText(outputFileName, output, host.FileEncoding);
foreach (CompilerError error in host.Errors)
Console.WriteLine(error.ToString());
Console.ReadLine();
}
}
}
Examining the transformer generated from the template showed lines like the following outside the TransformText() method. Seemingly, any literals in the source templates which came after a scriptlet (<#+ #>) would be placed in-fix into the generated generator class.
#line 1 "C:\dev\ImmutableObjectGraph-master\2013\Demo\Fruit.tt"
this.Write("\n");
Removing the newline characters at the end of each template file resolved the issue.

For me, the trailing newline at the end of the file was not a problem, but having Unix line endings (\n) instead of Windows line endings (\r\n) broke the T4 engine.
Very frustrating to debug when you have two files that look identical but one of them won't compile!

Yes, this was something to do with line ending for me too, possible due to source control.
To resolve, I copied and pasted the template code into Notepad++ and saved as a normal txt file then copy and pasted back.
(notepad didn't work as the line endings were wrong)

The line endings were the problem for me, too. (VS 2019) Edit > Advanced > Set End of Line Sequence > CRLF, then then transform worked.

Related

How to delete a Record from a List of files in a model in MVC3?

Hi all i have a TextBox and a Fileupload controll and a Table to show the uploaded Files...and i have a delete link in my table..so that user can delete any of the uploaded files before clicking on submit button....for this i have model
public BugModel()
{
if (ListFile == null)
ListFile = new List<BugAttachment>();
}
public List<BugAttachment> ListFile { get; set; }
}
public class BugAttachment
{
public string FileName { get; set; }
public int BugAttachmentID { get; set; }
public string AttachmentName { get; set; }
public int BugID { get; set; }
public string AttachmentUrl { get; set; }
public string AttachedBy { get; set; }
public string ErrorMessage { get; set; }
}
when ever user uploads a file i keep them in Listfile list and show them in table..now what i want is i want to delete the uploaded file from server and from the Listfile also
..i had succede deleting the file from uploaded files folder ...now i want to remove the AttachmentName and AttachmentUrl from my ListFile also when ever user clicks on delete link..how should i do this..any ideas are much appreciated
this is what i had done till now
public ActionResult Delete(string FileName, BugModel model)
{
if (Session["CaptureData"] == null)
{
}
else
{
model = (BugModel)Session["CaptureData"];
}
char DirSeparator = System.IO.Path.DirectorySeparatorChar;
string FilesPath = ";" + FileName;
string filenameonly = name + Path.GetFileName(FilesPath);
string FPath = "Content" + DirSeparator + "UploadedFiles" + DirSeparator + filenameonly;
// Don't do anything if there is no name
if (FileName.Length == 0) return View();
// Set our full path for deleting
string path = FilesPath + DirSeparator;
// Check if our file exists
if (System.IO.File.Exists(Path.GetFullPath(AppDomain.CurrentDomain.BaseDirectory + FPath)))
{
// Delete our file System.IO.File.Delete(Path.GetFullPath(AppDomain.CurrentDomain.BaseDirectory + FPath));
}
return View("LoadBug");
}
If the FileName is unique, you can create a new List of BugAttachments objects and exclude a particular object with the specified FileName
List<BugAttachment> allBugAttachemnts=GetAllAttachmentsFromSomeWhere();
List<BugAttachment> newBugAttachments = allBugAttachemnts.ListFile.
Where(x => x.FileName!= FileName).ToList();
Now newBugAttachments will have the Items after deletion.
You may also useRemoveAll method which updates the original List
allBugAttachemnts.RemoveAll(x => x.FileName!= FileName);
Assuming GetAllAttachmentsFromSomeWhere method returns a List of Available BugAttachment objects for the specified BugModel and FileName is the parameter which has the FileName to be deleted

How to restrict the file types in FileUpload in MVC3?

I have a fileupload function where users can upload files. I want to restrict the users from upload certain file types. The types allowed are: .doc,.xlsx,.txt,.jpeg.
How I can do this?
This is my actual file upload code:
public ActionResult UploadFile(string AttachmentName, BugModel model)
{
BugModel bug = null;
if (Session["CaptureData"] == null)
{
bug = model;
}
else
{
bug = (BugModel)Session["CaptureData"];
}
foreach (string inputTagName in Request.Files)
{
HttpPostedFileBase file1 = Request.Files[inputTagName];
if (file1.ContentLength > 0)
{
string path = "/Content/UploadedFiles/" + Path.GetFileName(file1.FileName);
string savedFileName = Path.Combine(Server.MapPath("~" + path));
file1.SaveAs(savedFileName);
BugAttachment attachment = new BugAttachment();
attachment.FileName = "~" + path.ToString();
attachment.AttachmentName = AttachmentName;
attachment.AttachmentUrl = attachment.FileName;
bug.ListFile.Add(attachment);
model = bug;
Session["CaptureData"] = model;
}
}
ModelState.Clear();
return View("LoadBug", bug);
}
The first thing to verify is whether the file extension contained in file1.FileName matches one of the allowed extensions. Then if you really want to ensure that the user hasn't renamed some other file type to an allowed extension you will need to look into the contents of the file to recognize whether it is one of the allowed types.
Here's an example how to check whether the file extension belongs to a list of predefined extensions:
var allowedExtensions = new[] { ".doc", ".xlsx", ".txt", ".jpeg" };
var extension = Path.GetExtension(file1.FileName);
if (!allowedExtensions.Contains(extension))
{
// Not allowed
}
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class AllowedFileExtensionAttribute : ValidationAttribute
{
public string[] AllowedFileExtensions { get; private set; }
public AllowedFileExtensionAttribute(params string[] allowedFileExtensions)
{
AllowedFileExtensions = allowedFileExtensions;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var file = value as HttpPostedFileBase;
if (file != null)
{
if (!AllowedFileExtensions.Any(item => file.FileName.EndsWith(item, StringComparison.OrdinalIgnoreCase)))
{
return new ValidationResult(string.Format("{1} için izin verilen dosya uzantıları : {0} : {2}", string.Join(", ", AllowedFileExtensions), validationContext.DisplayName, this.ErrorMessage));
}
}
return null;
}
}
Usage In Model
[AllowedFileExtension(".jpg", ".png", ".gif", ".jpeg")]
public HttpPostedFileBase KategoriResmi { get; set; }
You can use the ContentType property of the HttpPostedFileBase for a basic check of the file type (mime type): See MSDN's page on the Content-Type property here
Here is one way to do it:
private static bool IsValidContentType(string contentType)
{
string ct = contentType.ToLower();
return ((ct == "application/msword") || (ct == "application/pdf") || (ct == "application/vnd.openxmlformats-officedocument.wordprocessingml.document"));
}
etc..
However, for a deeper inspection, you will have to inspect the file content. It's easy to change a file extension..

Can I have a global razor #helper outside of App_Code?

The question is simple as stated in the title: Is there a way of having razor helpers outside of 'App_Code'?
Example ( HtmlEx.cshtml file ):
#helper Script(string fileName, UrlHelper url)
{
<script src="#url.Content("~/Scripts/" + fileName)" type="text/javascript"></script>
}
I ask this because I don't really have anything else to put in App_Code; I want to structure my project a bit different.
Thanks.
UPDATE: I don't want any other type of extensions. I am interested in only pure razor helpers as Scott is speaking about here: http://weblogs.asp.net/scottgu/archive/2011/05/12/asp-net-mvc-3-and-the-helper-syntax-within-razor.aspx
The question is simple as stated in the title: Is there a way of
having razor helpers outside of 'App_Code'?
No, there isn't.
Never Say Never...
Method One: (For use in a web application project)
Just add a pre-build event to copy your file into the App_Code folder.
(But since the file must probably be included in the project, you can add an empty file with the same name to the App_Code dir, and then have the build event to update it.)
(Note, that even if you put the file originally in the App_code folder you won't get intellisense until first time building, so it is anyway not a difference.)
Method Two: (for use in a class library, in which the startup project is a web application)
In a class library the App_Code folder is not anything special, so in order to be able to have the helper page global, we have to override the razor code, as it is hard coded to make global helpers only for code in the App_code folder.
Further more the razor code is designed so that for global helpers it creates a namespace based on the full path, something that you are probably not interested.
After all we remain with a problem, that there is no intellisense available, so to avoid all these problems, I have written the following code, assuming that:
Your .cshtml (or vbhtml) files are getting copied to the final projects output directory
You add a .cs (or .vb) file with the same name as the global helpers filename, and set it's build action to "compile", (this file will be autogenerated at startup to provide intellisense)
You have to register the PreApplicationStartupClass in the AssemblyInfo.cs file
You have to replace in the PreApplicationStartupCode.Start() method, to give the relative path to your global helpers page in the Bin folder, in the order of dependency (i.e. if one of the global helper files uses helpers in the other file then it should be listed after it).
In the CustomRazorCodeHost class you have to pick the correct method of PostProcessGeneratedCode() that is appropriate for the MVC version installed
Here is the code (but one will have to add the appropriate "using" statements):
[EditorBrowsable(EditorBrowsableState.Never)]
public static class PreApplicationStartCode
{
private static bool _startWasCalled;
public static void Start()
{
// Even though ASP.NET will only call each PreAppStart once, we sometimes internally call one PreAppStart from
// another PreAppStart to ensure that things get initialized in the right order. ASP.NET does not guarantee the
// order so we have to guard against multiple calls.
// All Start calls are made on same thread, so no lock needed here.
if (_startWasCalled)
{
return;
}
_startWasCalled = true;
//Add here the the global helpers based on dependency
//also note that each global helper should have a .cs file in the project with the same name
CustomRazorHelperBuildProvider bp = new CustomRazorHelperBuildProvider();
bp.VirtualPath = "~/Bin/path/to/helpers/file/Helpers.cshtml";
bp.GenerateCodeAndCompile();
bp = new CustomRazorHelperBuildProvider();
bp.VirtualPath = "~/Bin/path/to/helpers/file/DepndentHelpers.cshtml";
bp.GenerateCodeAndCompile();
}
}
public class CustomRazorHelperBuildProvider :RazorBuildProvider
{
static List<string> GeneratedAssemblyReferences = new List<string>();
public new string VirtualPath { get; set; }
protected override System.Web.WebPages.Razor.WebPageRazorHost CreateHost()
{
return new CustomCodeRazorHost(VirtualPath);
}
private WebPageRazorHost _host;
internal WebPageRazorHost Host
{
get
{
if (_host == null)
{
_host = CreateHost();
}
return _host;
}
}
private CodeCompileUnit _generatedCode = null;
internal CodeCompileUnit GeneratedCode
{
get
{
if (_generatedCode == null)
{
EnsureGeneratedCode();
}
return _generatedCode;
}
}
private CodeDomProvider _provider = null;
internal CodeDomProvider Provider
{
get
{
if(_provider == null)
{
_provider = GetProvider();
}
return _provider;
}
}
private void EnsureGeneratedCode()
{
RazorTemplateEngine engine = new RazorTemplateEngine(Host);
GeneratorResults results = null;
using (TextReader reader = OpenReader(VirtualPath))
{
results = engine.GenerateCode(reader, className: null, rootNamespace: null, sourceFileName: Host.PhysicalPath);
}
if (!results.Success)
{
RazorError error = results.ParserErrors.Last();
throw new HttpParseException(error.Message + Environment.NewLine, null, VirtualPath, null, error.Location.LineIndex + 1);
}
_generatedCode = results.GeneratedCode;
}
private CodeDomProvider GetProvider()
{
CompilerType compilerType = GetDefaultCompilerTypeForLanguage(Host.CodeLanguage.LanguageName);
CodeDomProvider provider = CreateCodeDomProviderWithPropertyOptions(compilerType.CodeDomProviderType);
return provider;
}
/// <summary>
/// Generates the c# (or vb.net) code, for the intellisense to work
/// </summary>
public void GenerateCode()
{
//Remember that if there is a razor error, then the next time the project will not compile at all, because the generated .cs file will also have the error!
//The solution is to add a pre-build event to truncate the file, but not remove it!, also note that the pre-build event will not work in time if the .cs file is open in the VS editor!
string filePath = VirtualPath.Replace("/", "\\").Replace("~\\Bin", "").Replace("\\Debug", "").Replace("\\Release", "");
filePath = filePath.Remove(filePath.Length - 4);
//filePath = filePath.Insert(filePath.LastIndexOf("\\"), "\\HelperAutoGeneratedCode");
Assembly curAssem = Assembly.GetExecutingAssembly();
filePath = HttpRuntime.AppDomainAppPath + "\\..\\" + curAssem.GetName().Name + filePath;
using (FileStream fs = new FileStream(filePath, FileMode.Truncate))
{
using (StreamWriter sw = new StreamWriter(fs))
{
Provider.GenerateCodeFromCompileUnit(GeneratedCode, sw, null);
sw.Flush();
sw.Close();
}
fs.Close();
}
//We need to replace the type of the helpers from "HelperResult" to object, otherwise the intellisense will complain that "it can't convert from HelperResult to object"
string text = File.ReadAllText(filePath);
text = text.Replace("public static System.Web.WebPages.HelperResult ", "public static object ");
File.WriteAllText(filePath, text);
}
public void GenerateCodeAndCompile()
{
GenerateCode();
Compile();
}
/// <summary>
/// Compiles the helper pages for use at runtime
/// </summary>
/// <returns>Compiler Result</returns>
public CompilerResults Compile()
{
Assembly assem = Assembly.GetExecutingAssembly();
AssemblyName[] references = assem.GetReferencedAssemblies();
List<string> referenceNames = references.Select(r => Assembly.ReflectionOnlyLoad(r.FullName).Location).ToList();
referenceNames.Add(assem.Location);
//Add here references that are not included in the project, but are needed for the generated assembly, you can see this through the results.Errors
referenceNames.Add((typeof(WebMatrix.Data.ConnectionEventArgs).Assembly.Location));
referenceNames.Add((typeof(WebMatrix.WebData.SimpleRoleProvider).Assembly.Location));
if (GeneratedAssemblyReferences != null && GeneratedAssemblyReferences.Count > 0)
{
referenceNames.AddRange(GeneratedAssemblyReferences);
}
CompilerResults results = Provider.CompileAssemblyFromDom(new CompilerParameters(referenceNames.ToArray()), new CodeCompileUnit[] { GeneratedCode });
if (results.Errors.HasErrors)
{
IEnumerator en = results.Errors.GetEnumerator();
en.MoveNext();
CompilerError error = en.Current as CompilerError;
throw new HttpParseException(error.ErrorText + Environment.NewLine, null, VirtualPath, null, error.Line);
}
Assembly assemblyRef = GetGeneratedType(results).Assembly;
GeneratedAssemblyReferences.Add(assemblyRef.Location); //So that any subsequent helper page that is dependent on it will have it as a reference
//We need to make it available for Razor, so it will work with reguler razor pages at runtime
RazorBuildProvider.CodeGenerationStarted += new EventHandler((sender, args) => (sender as RazorBuildProvider).AssemblyBuilder.AddCodeCompileUnit(this, GeneratedCode));
return results;
}
private static CodeDomProvider CreateCodeDomProviderWithPropertyOptions(Type codeDomProviderType)
{
// The following resembles the code in System.CodeDom.CompilerInfo.CreateProvider
// Make a copy to avoid modifying the original.
var originalProviderOptions = GetProviderOptions(codeDomProviderType);
IDictionary<string, string> providerOptions = null;
if (originalProviderOptions != null)
{
providerOptions = new Dictionary<string, string>(originalProviderOptions);
}
AssemblyName[] references = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
foreach (AssemblyName reference in references)
{
if (reference.Name == "mscorlib")
{
providerOptions["CompilerVersion"] = "v" + reference.Version.Major + "." + reference.Version.Minor;
break;
}
}
if (providerOptions != null && providerOptions.Count > 0)
{
ConstructorInfo ci = codeDomProviderType.GetConstructor(new Type[] { typeof(IDictionary<string, string>) });
CodeDomProvider provider = null;
if (ci != null)
{
// First, obtain the language for the given codedom provider type.
CodeDomProvider defaultProvider = (CodeDomProvider)Activator.CreateInstance(codeDomProviderType);
string extension = defaultProvider.FileExtension;
// Then, use the new createProvider API to create an instance.
provider = CodeDomProvider.CreateProvider(extension, providerOptions);
}
return provider;
}
return null;
}
internal static IDictionary<string, string> GetProviderOptions(Type codeDomProviderType)
{
// Using reflection to get the property for the time being.
// This could simply return CompilerInfo.PropertyOptions if it goes public in future.
CodeDomProvider provider = (CodeDomProvider)Activator.CreateInstance(codeDomProviderType);
string extension = provider.FileExtension;
if (CodeDomProvider.IsDefinedExtension(extension))
{
CompilerInfo ci = CodeDomProvider.GetCompilerInfo(CodeDomProvider.GetLanguageFromExtension(extension));
PropertyInfo pi = ci.GetType().GetProperty("ProviderOptions",
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance);
if (pi != null)
return (IDictionary<string, string>)pi.GetValue(ci, null);
return null;
}
return null;
}
}
public class CustomCodeRazorHost : WebPageRazorHost
{
internal const string ApplicationInstancePropertyName = "ApplicationInstance";
internal const string ContextPropertyName = "Context";
internal const string WebDefaultNamespace = "ASP";
private static readonly string _helperPageBaseType = typeof(HelperPage).FullName;
public CustomCodeRazorHost(string virtualPath)
: base(virtualPath)
{
DefaultBaseClass = _helperPageBaseType;
DefaultNamespace = WebDefaultNamespace;
DefaultDebugCompilation = false;
StaticHelpers = true;
}
//Version for MVC 3
public override void PostProcessGeneratedCode(CodeCompileUnit codeCompileUnit, CodeNamespace generatedNamespace, CodeTypeDeclaration generatedClass, CodeMemberMethod executeMethod)
{
// Add additional global imports
generatedNamespace.Imports.AddRange(GetGlobalImports().Select(s => new CodeNamespaceImport(s)).ToArray());
// Create ApplicationInstance property
CodeMemberProperty prop = new CodeMemberProperty()
{
Name = ApplicationInstancePropertyName,
Type = new CodeTypeReference(typeof(HttpApplication).FullName),
HasGet = true,
HasSet = false,
Attributes = MemberAttributes.Family | MemberAttributes.Final
};
prop.GetStatements.Add(
new CodeMethodReturnStatement(
new CodeCastExpression(
new CodeTypeReference(typeof(HttpApplication).FullName),
new CodePropertyReferenceExpression(
new CodePropertyReferenceExpression(
null,
ContextPropertyName),
ApplicationInstancePropertyName))));
generatedClass.Members.Insert(0, prop);
// Yank out the execute method (ignored in Razor Web Code pages)
generatedClass.Members.Remove(executeMethod);
// Make ApplicationInstance static
CodeMemberProperty appInstanceProperty =
generatedClass.Members
.OfType<CodeMemberProperty>()
.Where(p => ApplicationInstancePropertyName
.Equals(p.Name))
.SingleOrDefault();
if (appInstanceProperty != null)
{
appInstanceProperty.Attributes |= MemberAttributes.Static;
}
}
//Version for MVC 4
public override void PostProcessGeneratedCode(CodeGeneratorContext context)
{
// Add additional global imports
context.Namespace.Imports.AddRange(GetGlobalImports().Select(s => new CodeNamespaceImport(s)).ToArray());
// Create ApplicationInstance property
CodeMemberProperty prop = new CodeMemberProperty()
{
Name = ApplicationInstancePropertyName,
Type = new CodeTypeReference(typeof(HttpApplication).FullName),
HasGet = true,
HasSet = false,
Attributes = MemberAttributes.Family | MemberAttributes.Final
};
prop.GetStatements.Add(
new CodeMethodReturnStatement(
new CodeCastExpression(
new CodeTypeReference(typeof(HttpApplication).FullName),
new CodePropertyReferenceExpression(
new CodePropertyReferenceExpression(
null,
ContextPropertyName),
ApplicationInstancePropertyName))));
context.GeneratedClass.Members.Insert(0, prop);
// Yank out the execute method (ignored in Razor Web Code pages)
context.GeneratedClass.Members.Remove(context.TargetMethod);
// Make ApplicationInstance static
CodeMemberProperty appInstanceProperty =
context.GeneratedClass.Members
.OfType<CodeMemberProperty>()
.Where(p => ApplicationInstancePropertyName
.Equals(p.Name))
.SingleOrDefault();
if (appInstanceProperty != null)
{
appInstanceProperty.Attributes |= MemberAttributes.Static;
}
}
protected override string GetClassName(string virtualPath)
{
return ParserHelpers.SanitizeClassName(Path.GetFileNameWithoutExtension(virtualPath));
}
}
But note that if there is a syntax error in the .cshtml file, you will have problems to compile next time (as the generated .cs file will have compile errors), however visual studio apparently has problems to pinpoint the problem.
Also sometimes the compiled code from the last build (compiled from the .cs file), can sometimes conflict with the newly updated .cshtml file.
Therefore I would recommend to add a pre-build event to truncate the file
echo. > $(ProjectDir)\Path\to\.cs\file
you can go more sophisticated and do it only if the .cshtml file has been changed (and this also applies to the code I have written above).
Use the Razor Generator extension on a view with helpers inside and you'll generate the code for the view before compilation time. The generated view code is part of your project and compiles into the assembly, so you can place the view file anywhere and use the helpers anywhere, even from a unit test.
sure, you can put them anywhere in your code or project structure. in the file where you create your helper be sure to include using System.Web.Mvc.
then just normally extend the Helper class like this:
namespace System.Web.Mvc
{
static class HtmlHelperExtensions
{
public static IHtmlString MyNewHelper(this HtmlHelper helper, string someParam)
{
// do something
}
}
}

Why would running Pex Explorations result in ignoring a previously Pex-generated test method?

Code being tested:
public class TestReader
{
public string Content { get; private set; }
public void LoadFile(string fileName)
{
var content = FileSystem.ReadAllText(fileName);
if (!content.StartsWith("test"))
throw new ArgumentException("invalid file");
this.Content = content;
}
}
public static class FileSystem
{
public static string ReadAllText(string fileName)
{
return File.ReadAllText(fileName);
}
}
Pex method in test project:
[PexMethod]
public void CheckValidFileWithPex(string content)
{
// arrange
var fileName = "test.txt";
Moles_Example.Moles.MFileSystem.ReadAllTextString =
delegate(string f)
{
Assert.IsTrue(f == fileName); return content;
};
// act
var test = new TestReader();
test.LoadFile(fileName);
// assert
Assert.AreEqual(content, test.Content);
}
When I first run "Pex Explorations" on CheckValidFileWithPex(string content), five test methods are generated with the following values for content:
null
""
"\0\0\0\0"
"test"
"\0\0\0\0\0"
However, if I run "Pex Explorations" again, no changes made to the generated tests, existing test project code, or main project prior to second execution, then only 4 tests are listed as generated and the test input from item 3 ("\0\0\0\0") is missing.
The source code of the Pex-generated test file still has a test method for this case, but I do not understand why this case is not listed in Pex Exploration Results.
Thank you for your insight.

EF/Linq enum error

Given the following code:
public class RMAInfo
{
public enum RMAStatuses {
Undefined = 0, Approved = 1, Denied = 2,
Pending = 3, Received = 4, Closed = 5
}
public enum ReturnLocations { Undefined = 0, Utah = 1, Indy = 2 }
public RMAInfo()
{
ID = -1;
RMACode = string.Empty;
}
public int ID { get; set; }
public string RMACode { get; set; }
public string ResellerID { get; set; }
public RMAStatuses RMAStatus { get; set; }
}
private List<RMAInfo> GetRMAInfos_Internal(string resellerID)
{
List<RMAInfo> returnRMAInfos = new List<RMAInfo>();
using (Models.RMAEntities context = new Models.RMAEntities())
{
returnRMAInfos = (from r in context.RMAs
where r.ResellerID == resellerID
select new RMAInfo
{
ID = r.ID,
RMACode = r.RMACode,
ResellerID = r.ResellerID,
// error on next line!
RMAStatus = RMAInfo.RMAStatuses.Pending
}).ToList();
}
return returnRMAInfos;
}
I am getting an error on the assignment to the RMAStatus field. The error is
The specified value is not an instance of type 'Edm.Int32'
If I comment out that line, it works fine.
I have also tried to do this same code without using EF, and it seems to work fine.
Any ideas?
Entity Framework does not like the enum, as it cannot translate it to SQL. You would need to expose a way for EF to set the underlying int value, or you would have to set the value yourself once EF was done with it.
What you might do is expose an int property to set it. If you wish, you could restrict it to internal access so that perhaps callers can't see it but your EF code can (assuming callers are in different assemblies, but your context is not). Then you could have
public class RMAInfo
{
///<summary>
/// Integer representation of RMAStatus
///</summary>
internal int RMAStatusCode
{
get { return (int)this.RMAStatus; } // you could omit the getter
set { this.RMAStatus = (RMAInfo.RMAStatuses)value; }
}
}
...
select new RMAInfo
{
...
RMAStatusCode = (int)RMAInfo.RMAStatuses.Pending
}
To avoid this, you would basically select your RMAInfo sans status, and then iterate over the result to set each status to pending, leaving EF out of it entirely.
Installing .Net 4.5 appears to fix the issue as well (your project can still be on 4.0).
I was having this issue on our staging server (dev and test servers worked fine) and discovered that it did not have .Net 4.5 installed. Once I installed 4.5, the issue cleared up without any code changes.

Resources