How to upload file with Asp.net Web Api project? - vb.net

i have a web API project to be consumed from mobile applications and i was trying to make a file upload controller. there are few resources in C# and i don't find anything useful for VB.NET.
i tried this code below converting from c# to VB.NET, but says "Move is not a member of MultiPartFileData".
Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Linq
Imports System.Net
Imports System.Net.Http
Imports System.Threading.Tasks
Imports System.Web
Imports System.Web.Http
Namespace HelloWorld.Controller
Public Class FileUploadingController
Inherits ApiController
<HttpPost>
<Route("api/FileUploading/UploadFile")>
Public Async Function UploadFile() As Task(Of String)
Dim ctx = HttpContext.Current
Dim root = ctx.Server.MapPath("~/App_Data")
Dim provider = New MultipartFormDataStreamProvider(root)
Try
Await Request.Content.ReadAsMultipartAsync(provider)
For Each file In provider.FileData
Dim name = file.Headers.ContentDisposition.FileName
name = name.Trim(""""c)
Dim localFileName = file.LocalFileName
Dim filePath = Path.Combine(root, name)
File.Move(localFileName, filePath)
Next
Catch e As Exception
Return $"Error: {e.Message}"
End Try
Return "File uploaded!"
End Function
End Class
End Namespace

That error message means the compiler think that you are trying to call a method from the MultiPartFileData class. The variable of type MultiPartFileData is the one called file (notice the lowercase) initialized in the For Each loop.
Instead you want to call the Move method from the System.IO.File class (notice the uppercase).
VB.NET services (always running in background looking to catch errors while you type) is case insensitive so, for it, the two names are the same and here arises the error emitted when you code that line.
The best solution is to avoid names like file for your variables when you plan to use the class System.IO.File. Otherwise you could simply add the full qualified method's name in this way
System.IO.File.Move(localFileName, filePath)

Related

How do I make a property of a custom control open a file dialog?

I have a custom control with a property that holds the name (full path) to a file location that exists on the target computer.
The exact path will vary according to type of target pc and is typically set right after I add the custom control to my Form, while I am still in design mode of my project, so that when my application runs, it picks up the filename from the property.
It would be convenient if the property opened a file dialog to let me browse to the location (similar to how dialogs are opened when browsing for image and color properties), but this doesn't seem to be possible in visual basic.
After googling for days I have found a couple of articles that touch the subject for other programming languages (see example snippet below) but I haven't been able to work out how to make it work for visual basic.
Here is a snippet I found that mentions the use of an editor, which may be a clue to get started.
[Editor(typeof(FileSelectorTypeEditor), typeof(UITypeEditor))]
public string Filename
{
get { return _filename; }
set { _filename = value; }
}
Hope someone out there can lead me in the right way.
FileSelectorTypeEditor is probably a custom class derived from either FileNameEditor or FolderNameEditor.
You can implement both, using the standard class or extend the default with your own, as you have seen in those C# sources you have found.
Here I'm using a specialized FileNameEditor class, named (with some lack of imagination) SpecializedFileNameEditor and the standard FolderNameEditor assigning the UITypeEditor to two properties of a class.
► The ImagePath property editor is the SpecializedFileNameEditor object, which uses an OpenFileDialog, where a filter is pre-selected. It also overrides the EditValue method, to set the current value, if any, of an associated property (here, ImagePath) as the InitialDirectory of the OpenFileDialog.
► The ImageFolder property editor is a standard FolderNameEditor, which opens a FolderBrowserDialog.
I'm also attaching an ExpandableObjectConverter type converter, so you can present the two properties as an expandable property selector in a PropertyGrid.
You can see an example here:
How to bind child Controls of a User Control to a Public Property
Imports System.ComponentModel
Imports System.Drawing.Design
Imports System.IO
Imports System.Windows.Forms
Imports System.Windows.Forms.Design
<TypeConverter(GetType(ExpandableObjectConverter))>
Public Class ImagePickerClass
Public Sub New()
' Initialize [...]
End Sub
<Editor(GetType(SpecializedFileNameEditor), GetType(UITypeEditor))>
Public Property ImagePath As String
<Editor(GetType(FolderNameEditor), GetType(UITypeEditor))>
Public Property ImageFolder As String
Public Class SpecializedFileNameEditor
Inherits FileNameEditor
Private currentValue As String = String.Empty
Public Overrides Function EditValue(context As ITypeDescriptorContext, provider As IServiceProvider, value As Object) As Object
If TypeOf value Is String Then
currentValue = DirectCast(value, String)
End If
Return MyBase.EditValue(context, provider, value)
End Function
Protected Overrides Sub InitializeDialog(ofd As OpenFileDialog)
MyBase.InitializeDialog(ofd)
If Not currentValue.Equals(String.Empty) Then
ofd.InitialDirectory = Path.GetDirectoryName(currentValue)
End If
ofd.Filter = "PNG Images (*.png)|*.png"
End Sub
End Class
End Class

COM Visible Assembly - Object method not accessible through its exposed interface method

I implemented a .NET DLL with COM visibility (VB.NET):
Public Class Processer Implements IProcesser
Public Sub processASpecificThing(ByVal param As String) _
Implements IProcesser.processAThing
' [...]
End Sub
End Class
Below the Interface definition. For some reasons I exposed a method with a different name in the interface.
Imports System.Runtime.InteropServices
Imports System.ComponentModel
<InterfaceType(ComInterfaceType.InterfaceIsDual)> _
Public Interface IProcesser
Sub processAThing(ByVal param As String)
End Interface
The project is configured to set the Assembly as COM visible. If I understood correctly InterfaceIsDual let the Interface be visible at early binding as well as at late binding.
In a VB6 project, this works:
Dim aProcesser as IProcesser
Set aProcesser = New Processer
aProcesser.processAThing "param" ' Call by the *Interface* method name
In a VB6 project or an ASP classic VBScript page, this fails:
Dim aProcesser
Set aProcesser = CreateObject("ProcessLib.Processer")
' Call by the *Interface* method name
aProcesser.processAThing "param" ' [FAIL]
' Call by the *Interface* method name
aProcesser.processASpecificThing "param" ' [SUCCESS]
The failing line leads to the error message:
Object Doesn't Support this Property or Method
The real context of this question is an ASP classic page. I use a late binding to avoid adding a METADATA header in the ASP file (I believe it's the only way, but not tested yet).
Sounds like the interface is not accessible. Why does that problem occur and how could I make the interface accessible with ?

Best way to future proof software that opens files with default application interactively

I have created a VB .NET application that opens files in their default application - extracts information and returns it to a listview on a form.
All of the code is in my main form. The main form has in it
Imports Microsoft.Office.Core
Imports Microsoft.Office.Interop.Word
Imports Microsoft.Office.Interop.Excel
If in the future I want to modify my software to include another filetype not thought of in this release, am I better off for all of the filetypes I wish to open (including office) adding new classes for each filetype and including the 'Imports' in the individual classes?
So for example I would have:
OpenFileDWG.vb
Imports Autodesk.AutoCAD.Runtime
OpenFileDOC.vb
Imports Microsoft.Office.Interop.Word
etc. etc.
Is this a standard approach? If I were to do this, could I use:
If exists LCase(My.Computer.FileSystem.GetFileInfo(Filepath).Extension) THEN
strFileOpener = OpenFileDWG & Extension
Private fileOpener As strFileOpener
Would this approach work, or would I still need to reference the .dll in the main application, making this approach unworthy?
If I were to use this approach, could I just give the .vb file as part of an update?
Any advice is much appreciated.
Seems to me like a classing case to use factory design pattern
Basically, the factory design pattern provides loose coupling between the factory created classes and the class that uses them.
Begin by separating the different file types to different classes, and have them all inherit a basic abstract class (MustInherit in vb.net).
Then create an factory class to create create the concrete implementation of every file reader class. (meaning for each file type).
I'll try to illustrate with a simple example:
'' Defines an abstract class that all FileReaders should inherit
Public MustInherit Class FileReader
Public MustOverride Function ReadFileContent(Path As String) As String
End Class
Now, all of the classes for reading files must inherit the FileReader class:
Public Class WordFileReader
Inherits FileReader
Public Override Function ReadFileContent(Path As String) As String
'' TODO: Add code to read the content of the word document and return it as a string.
End Function
End Class
Public Class ExcelFileReader
Inherits FileReader
Public Override Function ReadFileContent(Path As String) As String
'' TODO: Add code to read the content of the excel file and return it as a string.
End Function
End Class
Then you can use a simple factory method (read here to learn about the difference between factory methods and abstract factories) to create your classes:
Enum FileTypes
Word,
Excel
End Enum
Public Function GetFileReader(FileType As FileTypes) As FileReader
Dim FileReader as FileReader = Nothing
Select case FileType
Case FileTypes.Word:
FileReader = New WordFileReader()
Case FileTypes.Excel:
FileReader = New ExcelFileReader()
End Select
Return FileReader
End Function
To enable new file types add-ins you can use MEF to load the concrete classes.

How to Inject a parameter to constructor using unity

Hi I am using unity in WebAPI 1.0 and registered it under Global.asax.vb file as below
Dim container As IUnityContainer = New UnityContainer()
container.RegisterType(Of Car)(New InjectionConstructor(GetType(Integer)))
Now how do i pass integer value which is passed by the client application into car type using
Public Sub New(ByVal intUserId As Int32)
objCar = DependencyResolver.Current.GetService(Of car)()
End Sub
Can't find anything to use (ParameterOverride("intUserId", intUserId) within DependencyResolver
It is very similar as registering unity container with ASP.NET MVC. Though web api has a different execution pipe line. Follow these steps.
NB: I have converted this code from C# to VB using a converter. So I hope it is syntactically correct. Though it is accurate in c#.
1) Implement IDependencyResolver (Make sure you are resolving correct namespace here. IDependencyResolver should come from System.Web.Http.Dependencies. Make note of Imported namespaces.
Imports System.Collections.Generic
Imports System.Linq
Imports System.Web
Imports Microsoft.Practices.Unity
Imports System.Web.Http.Dependencies
Namespace YourNamespace.Framework
Public Class UnityApiDependencyResolver
Implements IDependencyResolver
Private _container As IUnityContainer = Nothing
Public Sub New(container As IUnityContainer)
Me._container = container
End Sub
Public Function GetService(serviceType As Type) As Object
Try
Return _container.Resolve(serviceType)
Catch generatedExceptionName As Exception
Return Nothing
End Try
End Function
Public Function GetServices(serviceType As Type) As IEnumerable(Of Object)
Try
Return _container.ResolveAll(serviceType)
Catch generatedExceptionName As Exception
Return Nothing
End Try
End Function
Public Function BeginScope() As IDependencyScope
Return Me
End Function
Public Sub Dispose()
'
End Sub
End Class
End Namespace
'=======================================================
'Service provided by Telerik (www.telerik.com)
'Conversion powered by NRefactory.
'Twitter: #telerik
'Facebook: facebook.com/telerik
'=======================================================
2) Configure your container either thgough config or through code.
3) Register your container in Global.asax.vb file
Dim container = New UnityContainer()
Dim section As UnityConfigurationSection = TryCast(ConfigurationManager.GetSection("unity"), UnityConfigurationSection)
section.Configure(container, "UnitySection")
'api dependency resolver
GlobalConfiguration.Configuration.DependencyResolver = New UnityApiDependencyResolver(container)
'=======================================================
'Service provided by Telerik (www.telerik.com)
'Conversion powered by NRefactory.
'Twitter: #telerik
'Facebook: facebook.com/telerik
'=======================================================
Thats it.
Now you can declare your dependency in any of your API controller and it will be injected by Unity
Public Sub New(repositoryFactory As IRepositoryFactory, serviceFactory As IServiceFactory)
Me.repositoryFactory = repositoryFactory
Me.serviceFactory = serviceFactory
End Sub
'=======================================================
'Service provided by Telerik (www.telerik.com)
'Conversion powered by NRefactory.
'Twitter: #telerik
'Facebook: facebook.com/telerik
'=======================================================
Your type registration is wrong as well. you have to specify either an interface or an abstract class as dependency and its concrete implementation as its mapping.
e.g
container.RegisterType(Of IContext, Context)()
I don't understand what are trying to achieve by mapping an integer value to car. Do you want car object to be loaded based on integer value in your parameter?

CruiseControl .Net Plugin Vb.net Error

I am trying to make my own Labeller plugin for Cruise Control .Net 1.4.3. I have made a class based on another plug in example but I keep getting an error
Class 'AssemblyVersionLabeller' must implement 'Function Generate(integrationResult As IIntegrationResult) As String' for interface 'ThoughtWorks.CruiseControl.Core.ILabeller'
Here is my code :
Imports Exortech.NetReflector
Imports ThoughtWorks.CruiseControl.Core
Imports ThoughtWorks.CruiseControl.Core.Util
Namespace NetAssembly.CCNet.Label
_
Public Class AssemblyVersionLabeller
Implements ILabeller
Public Sub Run(ByVal result As IIntegrationResult)
result.Label = Generate(result)
End Sub
Public Function Generate(ByVal integrationResult As IIntegrationResult) As String
Dim label As String = integrationResult.LastIntegration.Label
Return label
End Function
<ReflectorProperty("prefix", Required:=False)> _
Public Prefix As String = String.Empty
End Class
End Namespace
What am I doing wrong? What have I missed?
Background Info:
I am using VS2005. I cant use CrusieControl 1.4.4 RC2 (which has an Assembly Labeller) because my source control's plugin (SCM Anywhere) doesnt work with it.
I cannot judge just by looking at your code, but if you need a sample on how to write labellers (C# code though), you could take a look at BrekiLabeller code (written by me).
I believe you forgot the overrides decleration..
Public Overrides Function Generate